meta-ads-mcp 0.3.9__py3-none-any.whl → 0.4.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 -3
- meta_ads_mcp/core/__init__.py +1 -2
- meta_ads_mcp/core/insights.py +2 -369
- {meta_ads_mcp-0.3.9.dist-info → meta_ads_mcp-0.4.0.dist-info}/METADATA +4 -12
- {meta_ads_mcp-0.3.9.dist-info → meta_ads_mcp-0.4.0.dist-info}/RECORD +8 -8
- {meta_ads_mcp-0.3.9.dist-info → meta_ads_mcp-0.4.0.dist-info}/WHEEL +0 -0
- {meta_ads_mcp-0.3.9.dist-info → meta_ads_mcp-0.4.0.dist-info}/entry_points.txt +0 -0
- {meta_ads_mcp-0.3.9.dist-info → meta_ads_mcp-0.4.0.dist-info}/licenses/LICENSE +0 -0
meta_ads_mcp/__init__.py
CHANGED
|
@@ -7,7 +7,7 @@ with the Claude LLM.
|
|
|
7
7
|
|
|
8
8
|
from meta_ads_mcp.core.server import main
|
|
9
9
|
|
|
10
|
-
__version__ = "0.
|
|
10
|
+
__version__ = "0.4.0"
|
|
11
11
|
|
|
12
12
|
__all__ = [
|
|
13
13
|
'get_ad_accounts',
|
|
@@ -24,7 +24,6 @@ __all__ = [
|
|
|
24
24
|
'get_ad_image',
|
|
25
25
|
'update_ad',
|
|
26
26
|
'get_insights',
|
|
27
|
-
'debug_image_download',
|
|
28
27
|
'get_login_link',
|
|
29
28
|
'login_cli',
|
|
30
29
|
'main'
|
|
@@ -46,7 +45,6 @@ from .core import (
|
|
|
46
45
|
get_ad_image,
|
|
47
46
|
update_ad,
|
|
48
47
|
get_insights,
|
|
49
|
-
debug_image_download,
|
|
50
48
|
get_login_link,
|
|
51
49
|
login_cli,
|
|
52
50
|
main
|
meta_ads_mcp/core/__init__.py
CHANGED
|
@@ -5,7 +5,7 @@ from .accounts import get_ad_accounts, get_account_info
|
|
|
5
5
|
from .campaigns import get_campaigns, get_campaign_details, create_campaign
|
|
6
6
|
from .adsets import get_adsets, get_adset_details, update_adset
|
|
7
7
|
from .ads import get_ads, get_ad_details, get_ad_creatives, get_ad_image, update_ad
|
|
8
|
-
from .insights import get_insights
|
|
8
|
+
from .insights import get_insights
|
|
9
9
|
from .authentication import get_login_link
|
|
10
10
|
from .server import login_cli, main
|
|
11
11
|
from .auth import login
|
|
@@ -29,7 +29,6 @@ __all__ = [
|
|
|
29
29
|
'get_ad_image',
|
|
30
30
|
'update_ad',
|
|
31
31
|
'get_insights',
|
|
32
|
-
'debug_image_download',
|
|
33
32
|
'get_login_link',
|
|
34
33
|
'login_cli',
|
|
35
34
|
'login',
|
meta_ads_mcp/core/insights.py
CHANGED
|
@@ -56,374 +56,7 @@ async def get_insights(access_token: str = None, object_id: str = None,
|
|
|
56
56
|
return json.dumps(data, indent=2)
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
@mcp_server.tool()
|
|
60
|
-
@meta_api_tool
|
|
61
|
-
async def debug_image_download(access_token: str = None, url: str = "", ad_id: str = "") -> str:
|
|
62
|
-
"""
|
|
63
|
-
Debug image download issues and report detailed diagnostics.
|
|
64
|
-
|
|
65
|
-
Args:
|
|
66
|
-
access_token: Meta API access token (optional - will use cached token if not provided)
|
|
67
|
-
url: Direct image URL to test (optional)
|
|
68
|
-
ad_id: Meta Ads ad ID (optional, used if url is not provided)
|
|
69
|
-
"""
|
|
70
|
-
results = {
|
|
71
|
-
"diagnostics": {
|
|
72
|
-
"timestamp": str(datetime.datetime.now()),
|
|
73
|
-
"methods_tried": [],
|
|
74
|
-
"request_details": [],
|
|
75
|
-
"network_info": {}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
# If no URL provided but ad_id is, get URL from ad creative
|
|
80
|
-
if not url and ad_id:
|
|
81
|
-
print(f"Getting image URL from ad creative for ad {ad_id}")
|
|
82
|
-
# Get the creative details
|
|
83
|
-
from .ads import get_ad_creatives
|
|
84
|
-
creative_json = await get_ad_creatives(ad_id=ad_id, access_token=access_token)
|
|
85
|
-
creative_data = json.loads(creative_json)
|
|
86
|
-
results["creative_data"] = creative_data
|
|
87
|
-
|
|
88
|
-
# Look for image URL in the creative
|
|
89
|
-
if "full_image_url" in creative_data:
|
|
90
|
-
url = creative_data.get("full_image_url")
|
|
91
|
-
elif "thumbnail_url" in creative_data:
|
|
92
|
-
url = creative_data.get("thumbnail_url")
|
|
93
|
-
|
|
94
|
-
if not url:
|
|
95
|
-
return json.dumps({
|
|
96
|
-
"error": "No image URL provided or found in ad creative",
|
|
97
|
-
"results": results
|
|
98
|
-
}, indent=2)
|
|
99
|
-
|
|
100
|
-
results["image_url"] = url
|
|
101
|
-
|
|
102
|
-
# Try to get network information to help debug
|
|
103
|
-
try:
|
|
104
|
-
import socket
|
|
105
|
-
from urllib.parse import urlparse
|
|
106
|
-
hostname = urlparse(url).netloc
|
|
107
|
-
ip_address = socket.gethostbyname(hostname)
|
|
108
|
-
results["diagnostics"]["network_info"] = {
|
|
109
|
-
"hostname": hostname,
|
|
110
|
-
"ip_address": ip_address,
|
|
111
|
-
"is_facebook_cdn": "fbcdn" in hostname
|
|
112
|
-
}
|
|
113
|
-
except Exception as e:
|
|
114
|
-
results["diagnostics"]["network_info"] = {
|
|
115
|
-
"error": str(e)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
# Method 1: Basic download
|
|
119
|
-
method_result = {
|
|
120
|
-
"method": "Basic download with standard headers",
|
|
121
|
-
"success": False
|
|
122
|
-
}
|
|
123
|
-
results["diagnostics"]["methods_tried"].append(method_result)
|
|
124
|
-
|
|
125
|
-
try:
|
|
126
|
-
headers = {
|
|
127
|
-
"User-Agent": "curl/8.4.0"
|
|
128
|
-
}
|
|
129
|
-
import httpx
|
|
130
|
-
async with httpx.AsyncClient(follow_redirects=True) as client:
|
|
131
|
-
response = await client.get(url, headers=headers, timeout=30.0)
|
|
132
|
-
method_result["status_code"] = response.status_code
|
|
133
|
-
method_result["headers"] = dict(response.headers)
|
|
134
|
-
|
|
135
|
-
if response.status_code == 200:
|
|
136
|
-
method_result["success"] = True
|
|
137
|
-
method_result["content_length"] = len(response.content)
|
|
138
|
-
method_result["content_type"] = response.headers.get("content-type")
|
|
139
|
-
|
|
140
|
-
# Save this successful result
|
|
141
|
-
results["image_data"] = {
|
|
142
|
-
"length": len(response.content),
|
|
143
|
-
"type": response.headers.get("content-type"),
|
|
144
|
-
"base64_sample": base64.b64encode(response.content[:100]).decode("utf-8") + "..." if response.content else None
|
|
145
|
-
}
|
|
146
|
-
except Exception as e:
|
|
147
|
-
method_result["error"] = str(e)
|
|
148
|
-
|
|
149
|
-
# Method 2: Browser emulation
|
|
150
|
-
method_result = {
|
|
151
|
-
"method": "Browser emulation with cookies",
|
|
152
|
-
"success": False
|
|
153
|
-
}
|
|
154
|
-
results["diagnostics"]["methods_tried"].append(method_result)
|
|
155
|
-
|
|
156
|
-
try:
|
|
157
|
-
headers = {
|
|
158
|
-
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
|
|
159
|
-
"Accept": "image/webp,image/apng,image/*,*/*;q=0.8",
|
|
160
|
-
"Accept-Language": "en-US,en;q=0.9",
|
|
161
|
-
"Referer": "https://www.facebook.com/",
|
|
162
|
-
"Cookie": "presence=EDvF3EtimeF1697900316EuserFA21B00112233445566AA0EstateFDutF0CEchF_7bCC"
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
import httpx
|
|
166
|
-
async with httpx.AsyncClient(follow_redirects=True) as client:
|
|
167
|
-
response = await client.get(url, headers=headers, timeout=30.0)
|
|
168
|
-
method_result["status_code"] = response.status_code
|
|
169
|
-
method_result["headers"] = dict(response.headers)
|
|
170
|
-
|
|
171
|
-
if response.status_code == 200:
|
|
172
|
-
method_result["success"] = True
|
|
173
|
-
method_result["content_length"] = len(response.content)
|
|
174
|
-
method_result["content_type"] = response.headers.get("content-type")
|
|
175
|
-
|
|
176
|
-
# If first method didn't succeed, save this successful result
|
|
177
|
-
if "image_data" not in results:
|
|
178
|
-
results["image_data"] = {
|
|
179
|
-
"length": len(response.content),
|
|
180
|
-
"type": response.headers.get("content-type"),
|
|
181
|
-
"base64_sample": base64.b64encode(response.content[:100]).decode("utf-8") + "..." if response.content else None
|
|
182
|
-
}
|
|
183
|
-
except Exception as e:
|
|
184
|
-
method_result["error"] = str(e)
|
|
185
|
-
|
|
186
|
-
# Method 3: Graph API direct access (if applicable)
|
|
187
|
-
if "fbcdn" in url or "facebook" in url:
|
|
188
|
-
method_result = {
|
|
189
|
-
"method": "Graph API direct access",
|
|
190
|
-
"success": False
|
|
191
|
-
}
|
|
192
|
-
results["diagnostics"]["methods_tried"].append(method_result)
|
|
193
|
-
|
|
194
|
-
try:
|
|
195
|
-
# Try to reconstruct the attachment ID from URL if possible
|
|
196
|
-
from urllib.parse import urlparse
|
|
197
|
-
url_parts = urlparse(url).path.split("/")
|
|
198
|
-
potential_ids = [part for part in url_parts if part.isdigit() and len(part) > 10]
|
|
199
|
-
|
|
200
|
-
if potential_ids:
|
|
201
|
-
attachment_id = potential_ids[0]
|
|
202
|
-
endpoint = f"{attachment_id}?fields=url,width,height"
|
|
203
|
-
api_result = await make_api_request(endpoint, access_token)
|
|
204
|
-
|
|
205
|
-
method_result["api_response"] = api_result
|
|
206
|
-
|
|
207
|
-
if "url" in api_result:
|
|
208
|
-
graph_url = api_result["url"]
|
|
209
|
-
method_result["graph_url"] = graph_url
|
|
210
|
-
|
|
211
|
-
# Try to download from this Graph API URL
|
|
212
|
-
import httpx
|
|
213
|
-
async with httpx.AsyncClient() as client:
|
|
214
|
-
response = await client.get(graph_url, timeout=30.0)
|
|
215
|
-
|
|
216
|
-
method_result["status_code"] = response.status_code
|
|
217
|
-
if response.status_code == 200:
|
|
218
|
-
method_result["success"] = True
|
|
219
|
-
method_result["content_length"] = len(response.content)
|
|
220
|
-
|
|
221
|
-
# If previous methods didn't succeed, save this successful result
|
|
222
|
-
if "image_data" not in results:
|
|
223
|
-
results["image_data"] = {
|
|
224
|
-
"length": len(response.content),
|
|
225
|
-
"type": response.headers.get("content-type"),
|
|
226
|
-
"base64_sample": base64.b64encode(response.content[:100]).decode("utf-8") + "..." if response.content else None
|
|
227
|
-
}
|
|
228
|
-
except Exception as e:
|
|
229
|
-
method_result["error"] = str(e)
|
|
230
|
-
|
|
231
|
-
# Generate a recommendation based on what we found
|
|
232
|
-
if "image_data" in results:
|
|
233
|
-
results["recommendation"] = "At least one download method succeeded. Consider implementing the successful method in the main code."
|
|
234
|
-
else:
|
|
235
|
-
# Check if the error appears to be access-related
|
|
236
|
-
access_errors = False
|
|
237
|
-
for method in results["diagnostics"]["methods_tried"]:
|
|
238
|
-
if method.get("status_code") in [401, 403, 503]:
|
|
239
|
-
access_errors = True
|
|
240
|
-
|
|
241
|
-
if access_errors:
|
|
242
|
-
results["recommendation"] = "Authentication or authorization errors detected. Images may require direct Facebook authentication not possible via API."
|
|
243
|
-
else:
|
|
244
|
-
results["recommendation"] = "Network or other technical errors detected. Check URL expiration or CDN restrictions."
|
|
245
|
-
|
|
246
|
-
return json.dumps(results, indent=2)
|
|
247
59
|
|
|
248
60
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
async def save_ad_image_via_api(access_token: str = None, ad_id: str = None) -> str:
|
|
252
|
-
"""
|
|
253
|
-
Try to save an ad image by using the Marketing API's attachment endpoints.
|
|
254
|
-
This is an alternative approach when direct image download fails.
|
|
255
|
-
|
|
256
|
-
Args:
|
|
257
|
-
access_token: Meta API access token (optional - will use cached token if not provided)
|
|
258
|
-
ad_id: Meta Ads ad ID
|
|
259
|
-
"""
|
|
260
|
-
if not ad_id:
|
|
261
|
-
return json.dumps({"error": "No ad ID provided"}, indent=2)
|
|
262
|
-
|
|
263
|
-
# First get the ad's creative ID
|
|
264
|
-
endpoint = f"{ad_id}"
|
|
265
|
-
params = {
|
|
266
|
-
"fields": "creative,account_id"
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
ad_data = await make_api_request(endpoint, access_token, params)
|
|
270
|
-
|
|
271
|
-
if "error" in ad_data:
|
|
272
|
-
return json.dumps({
|
|
273
|
-
"error": "Could not get ad data",
|
|
274
|
-
"details": ad_data
|
|
275
|
-
}, indent=2)
|
|
276
|
-
|
|
277
|
-
if "creative" not in ad_data or "id" not in ad_data["creative"]:
|
|
278
|
-
return json.dumps({
|
|
279
|
-
"error": "No creative ID found for this ad",
|
|
280
|
-
"ad_data": ad_data
|
|
281
|
-
}, indent=2)
|
|
282
|
-
|
|
283
|
-
creative_id = ad_data["creative"]["id"]
|
|
284
|
-
account_id = ad_data.get("account_id", "")
|
|
285
|
-
|
|
286
|
-
# Now get the creative object
|
|
287
|
-
creative_endpoint = f"{creative_id}"
|
|
288
|
-
creative_params = {
|
|
289
|
-
"fields": "id,name,thumbnail_url,image_hash,asset_feed_spec"
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
creative_data = await make_api_request(creative_endpoint, access_token, creative_params)
|
|
293
|
-
|
|
294
|
-
if "error" in creative_data:
|
|
295
|
-
return json.dumps({
|
|
296
|
-
"error": "Could not get creative data",
|
|
297
|
-
"details": creative_data
|
|
298
|
-
}, indent=2)
|
|
299
|
-
|
|
300
|
-
# Approach 1: Try to get image through adimages endpoint if we have image_hash
|
|
301
|
-
image_hash = None
|
|
302
|
-
if "image_hash" in creative_data:
|
|
303
|
-
image_hash = creative_data["image_hash"]
|
|
304
|
-
elif "asset_feed_spec" in creative_data and "images" in creative_data["asset_feed_spec"] and len(creative_data["asset_feed_spec"]["images"]) > 0:
|
|
305
|
-
image_hash = creative_data["asset_feed_spec"]["images"][0].get("hash")
|
|
306
|
-
|
|
307
|
-
result = {
|
|
308
|
-
"ad_id": ad_id,
|
|
309
|
-
"creative_id": creative_id,
|
|
310
|
-
"attempts": []
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
if image_hash and account_id:
|
|
314
|
-
attempt = {
|
|
315
|
-
"method": "adimages endpoint with hash",
|
|
316
|
-
"success": False
|
|
317
|
-
}
|
|
318
|
-
result["attempts"].append(attempt)
|
|
319
|
-
|
|
320
|
-
try:
|
|
321
|
-
image_endpoint = f"act_{account_id}/adimages"
|
|
322
|
-
image_params = {
|
|
323
|
-
"hashes": [image_hash]
|
|
324
|
-
}
|
|
325
|
-
image_data = await make_api_request(image_endpoint, access_token, image_params)
|
|
326
|
-
attempt["response"] = image_data
|
|
327
|
-
|
|
328
|
-
if "data" in image_data and len(image_data["data"]) > 0 and "url" in image_data["data"][0]:
|
|
329
|
-
url = image_data["data"][0]["url"]
|
|
330
|
-
attempt["url"] = url
|
|
331
|
-
|
|
332
|
-
# Try to download the image
|
|
333
|
-
image_bytes = await download_image(url)
|
|
334
|
-
if image_bytes:
|
|
335
|
-
attempt["success"] = True
|
|
336
|
-
attempt["image_size"] = len(image_bytes)
|
|
337
|
-
|
|
338
|
-
# Save the image
|
|
339
|
-
resource_id = f"ad_creative_{ad_id}_method1"
|
|
340
|
-
resource_info = create_resource_from_image(
|
|
341
|
-
image_bytes,
|
|
342
|
-
resource_id,
|
|
343
|
-
f"Ad Creative for {ad_id} (Method 1)"
|
|
344
|
-
)
|
|
345
|
-
|
|
346
|
-
# Return success with resource info
|
|
347
|
-
result.update(resource_info)
|
|
348
|
-
result["success"] = True
|
|
349
|
-
base64_sample = base64.b64encode(image_bytes[:100]).decode("utf-8") + "..."
|
|
350
|
-
result["base64_sample"] = base64_sample
|
|
351
|
-
except Exception as e:
|
|
352
|
-
attempt["error"] = str(e)
|
|
353
|
-
|
|
354
|
-
# Approach 2: Try directly with the thumbnails endpoint
|
|
355
|
-
attempt = {
|
|
356
|
-
"method": "thumbnails endpoint on creative",
|
|
357
|
-
"success": False
|
|
358
|
-
}
|
|
359
|
-
result["attempts"].append(attempt)
|
|
360
|
-
|
|
361
|
-
try:
|
|
362
|
-
thumbnails_endpoint = f"{creative_id}/thumbnails"
|
|
363
|
-
thumbnails_params = {}
|
|
364
|
-
thumbnails_data = await make_api_request(thumbnails_endpoint, access_token, thumbnails_params)
|
|
365
|
-
attempt["response"] = thumbnails_data
|
|
366
|
-
|
|
367
|
-
if "data" in thumbnails_data and len(thumbnails_data["data"]) > 0:
|
|
368
|
-
for thumbnail in thumbnails_data["data"]:
|
|
369
|
-
if "uri" in thumbnail:
|
|
370
|
-
url = thumbnail["uri"]
|
|
371
|
-
attempt["url"] = url
|
|
372
|
-
|
|
373
|
-
# Try to download the image
|
|
374
|
-
image_bytes = await download_image(url)
|
|
375
|
-
if image_bytes:
|
|
376
|
-
attempt["success"] = True
|
|
377
|
-
attempt["image_size"] = len(image_bytes)
|
|
378
|
-
|
|
379
|
-
# Save the image if method 1 didn't already succeed
|
|
380
|
-
if "success" not in result or not result["success"]:
|
|
381
|
-
resource_id = f"ad_creative_{ad_id}_method2"
|
|
382
|
-
resource_info = create_resource_from_image(
|
|
383
|
-
image_bytes,
|
|
384
|
-
resource_id,
|
|
385
|
-
f"Ad Creative for {ad_id} (Method 2)"
|
|
386
|
-
)
|
|
387
|
-
|
|
388
|
-
# Return success with resource info
|
|
389
|
-
result.update(resource_info)
|
|
390
|
-
result["success"] = True
|
|
391
|
-
base64_sample = base64.b64encode(image_bytes[:100]).decode("utf-8") + "..."
|
|
392
|
-
result["base64_sample"] = base64_sample
|
|
393
|
-
|
|
394
|
-
# No need to try more thumbnails if we succeeded
|
|
395
|
-
break
|
|
396
|
-
except Exception as e:
|
|
397
|
-
attempt["error"] = str(e)
|
|
398
|
-
|
|
399
|
-
# Approach 3: Try using the preview shareable link as an alternate source
|
|
400
|
-
attempt = {
|
|
401
|
-
"method": "preview_shareable_link",
|
|
402
|
-
"success": False
|
|
403
|
-
}
|
|
404
|
-
result["attempts"].append(attempt)
|
|
405
|
-
|
|
406
|
-
try:
|
|
407
|
-
# Get ad details with preview link
|
|
408
|
-
ad_preview_endpoint = f"{ad_id}"
|
|
409
|
-
ad_preview_params = {
|
|
410
|
-
"fields": "preview_shareable_link"
|
|
411
|
-
}
|
|
412
|
-
ad_preview_data = await make_api_request(ad_preview_endpoint, access_token, ad_preview_params)
|
|
413
|
-
|
|
414
|
-
if "preview_shareable_link" in ad_preview_data:
|
|
415
|
-
preview_link = ad_preview_data["preview_shareable_link"]
|
|
416
|
-
attempt["preview_link"] = preview_link
|
|
417
|
-
|
|
418
|
-
# We can't directly download the preview image, but let's note it for manual inspection
|
|
419
|
-
attempt["note"] = "Preview link available for manual inspection in browser"
|
|
420
|
-
except Exception as e:
|
|
421
|
-
attempt["error"] = str(e)
|
|
422
|
-
|
|
423
|
-
# Overall result
|
|
424
|
-
if "success" in result and result["success"]:
|
|
425
|
-
result["message"] = "Successfully retrieved ad image through one of the API methods"
|
|
426
|
-
else:
|
|
427
|
-
result["message"] = "Failed to retrieve ad image through any API method"
|
|
428
|
-
|
|
429
|
-
return json.dumps(result, indent=2)
|
|
61
|
+
|
|
62
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meta-ads-mcp
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Model Calling 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
|
|
@@ -13,7 +13,7 @@ Classifier: Operating System :: OS Independent
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3
|
|
14
14
|
Requires-Python: >=3.10
|
|
15
15
|
Requires-Dist: httpx>=0.26.0
|
|
16
|
-
Requires-Dist: mcp[cli]>=1.
|
|
16
|
+
Requires-Dist: mcp[cli]>=1.10.1
|
|
17
17
|
Requires-Dist: pathlib>=1.0.1
|
|
18
18
|
Requires-Dist: pillow>=10.0.0
|
|
19
19
|
Requires-Dist: python-dateutil>=2.8.2
|
|
@@ -313,21 +313,13 @@ For local installation configuration, authentication options, and advanced techn
|
|
|
313
313
|
- `level`: Level of aggregation (ad, adset, campaign, account)
|
|
314
314
|
- Returns: Performance metrics for the specified object
|
|
315
315
|
|
|
316
|
-
20. `
|
|
317
|
-
- Debug image download issues and report detailed diagnostics
|
|
318
|
-
- Inputs:
|
|
319
|
-
- `access_token` (optional): Meta API access token (will use cached token if not provided)
|
|
320
|
-
- `url`: Direct image URL to test (optional)
|
|
321
|
-
- `ad_id`: Meta Ads ad ID (optional, used if url is not provided)
|
|
322
|
-
- Returns: Diagnostic information about image download attempts
|
|
323
|
-
|
|
324
|
-
21. `mcp_meta_ads_get_login_link`
|
|
316
|
+
20. `mcp_meta_ads_get_login_link`
|
|
325
317
|
- Get a clickable login link for Meta Ads authentication
|
|
326
318
|
- Inputs:
|
|
327
319
|
- `access_token` (optional): Meta API access token (will use cached token if not provided)
|
|
328
320
|
- Returns: A clickable resource link for Meta authentication
|
|
329
321
|
|
|
330
|
-
|
|
322
|
+
21. `mcp_meta-ads_create_budget_schedule`
|
|
331
323
|
- Create a budget schedule for a Meta Ads campaign.
|
|
332
324
|
- Inputs:
|
|
333
325
|
- `campaign_id`: Meta Ads campaign ID.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
meta_ads_mcp/__init__.py,sha256=
|
|
1
|
+
meta_ads_mcp/__init__.py,sha256=Ive8lkiVBTI71DtD75td68TiZ597_Br6xiYdVIbJaw0,1182
|
|
2
2
|
meta_ads_mcp/__main__.py,sha256=XaQt3iXftG_7f0Zu7Wop9SeFgrD2WBn0EQOaPMc27d8,207
|
|
3
|
-
meta_ads_mcp/core/__init__.py,sha256=
|
|
3
|
+
meta_ads_mcp/core/__init__.py,sha256=TQSAEn_c_n5ShXcgPXbzDNfIfiPUgJAGe3VIUvSyvjo,1124
|
|
4
4
|
meta_ads_mcp/core/accounts.py,sha256=Nmp7lPxO9wmq25jWV7_H0LIqnEbBhpCVBlLGW2HUaq0,2277
|
|
5
5
|
meta_ads_mcp/core/ads.py,sha256=b_81GlGHIM4jISvuDZmHNyc6uW7uD3ovX68ezBci9MM,29747
|
|
6
6
|
meta_ads_mcp/core/ads_library.py,sha256=onStn9UkRqYDC60gOPS-iKDtP1plz6DygUb7hUZ0Jw8,2807
|
|
@@ -12,14 +12,14 @@ meta_ads_mcp/core/budget_schedules.py,sha256=UxseExsvKAiPwfDCY9aycT4kys4xqeNytyq
|
|
|
12
12
|
meta_ads_mcp/core/callback_server.py,sha256=AUymElaVwHqFyqB2wgqf6A68KsqwtKoYmY-7JZZt8Ks,43286
|
|
13
13
|
meta_ads_mcp/core/campaigns.py,sha256=Fd477GsD1Gx08Ve0uXUCvr4fC-xQCeVHPBwRVaeRQKk,10965
|
|
14
14
|
meta_ads_mcp/core/http_auth_integration.py,sha256=ZJHuxK1Kwtr9gvwfC5HZOLH5MW-HnDDKqJc4xuG5yVE,10060
|
|
15
|
-
meta_ads_mcp/core/insights.py,sha256=
|
|
15
|
+
meta_ads_mcp/core/insights.py,sha256=U7KYdWQpGcdykE1WUtdJdYR3VTwKrXUzIzCREwWbf48,2599
|
|
16
16
|
meta_ads_mcp/core/pipeboard_auth.py,sha256=VvbxEB8ZOhnMccLU7HI1HgaPWHCl5NGrzZCm-zzHze4,22798
|
|
17
17
|
meta_ads_mcp/core/reports.py,sha256=Dv3hfsPOR7IZ9WrYrKd_6SNgZl-USIphg7knva3UYAw,5747
|
|
18
18
|
meta_ads_mcp/core/resources.py,sha256=-zIIfZulpo76vcKv6jhAlQq91cR2SZ3cjYZt3ek3x0w,1236
|
|
19
19
|
meta_ads_mcp/core/server.py,sha256=mmhtcyB7h1aO6jK4njLztPdAebPDmc3mhA7DksR1nlY,17583
|
|
20
20
|
meta_ads_mcp/core/utils.py,sha256=DsizDYuJnWUpkbShV1y5Qe8t47Qf59aPZ6O9v0hzdkY,6705
|
|
21
|
-
meta_ads_mcp-0.
|
|
22
|
-
meta_ads_mcp-0.
|
|
23
|
-
meta_ads_mcp-0.
|
|
24
|
-
meta_ads_mcp-0.
|
|
25
|
-
meta_ads_mcp-0.
|
|
21
|
+
meta_ads_mcp-0.4.0.dist-info/METADATA,sha256=qYEgWGno8pVxWx7qV9vK3GZwDsJhhkRTfX6dWaMeZ7M,17125
|
|
22
|
+
meta_ads_mcp-0.4.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
23
|
+
meta_ads_mcp-0.4.0.dist-info/entry_points.txt,sha256=Dv2RkoBjRJBqj6CyhwqGIiwPCD-SCL1-7B9-zmVRuv0,57
|
|
24
|
+
meta_ads_mcp-0.4.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
25
|
+
meta_ads_mcp-0.4.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|