meta-ads-mcp 0.4.2__tar.gz → 0.4.3__tar.gz
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-0.4.2 → meta_ads_mcp-0.4.3}/PKG-INFO +1 -1
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/__init__.py +1 -1
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/ads.py +9 -8
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/pyproject.toml +1 -1
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/tests/test_http_transport.py +72 -1
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/.github/workflows/publish.yml +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/.github/workflows/test.yml +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/.gitignore +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/CUSTOM_META_APP.md +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/Dockerfile +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/LICENSE +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/LOCAL_INSTALLATION.md +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/META_API_NOTES.md +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/README.md +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/RELEASE.md +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/STREAMABLE_HTTP_SETUP.md +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/examples/README.md +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/examples/example_http_client.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/future_improvements.md +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/images/meta-ads-example.png +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_auth.sh +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/__main__.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/__init__.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/accounts.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/ads_library.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/adsets.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/api.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/auth.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/authentication.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/budget_schedules.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/callback_server.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/campaigns.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/duplication.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/http_auth_integration.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/insights.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/pipeboard_auth.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/reports.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/resources.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/server.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/utils.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/requirements.txt +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/setup.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/smithery.yaml +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/tests/README.md +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/tests/README_REGRESSION_TESTS.md +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/tests/__init__.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/tests/conftest.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/tests/test_duplication.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/tests/test_duplication_regression.py +0 -0
- {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/tests/test_openai.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meta-ads-mcp
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
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
|
|
@@ -38,26 +38,27 @@ async def get_ads(access_token: str = None, account_id: str = None, limit: int =
|
|
|
38
38
|
else:
|
|
39
39
|
return json.dumps({"error": "No account ID specified and no accounts found for user"}, indent=2)
|
|
40
40
|
|
|
41
|
+
# Prioritize adset_id over campaign_id - use adset-specific endpoint
|
|
42
|
+
if adset_id:
|
|
43
|
+
endpoint = f"{adset_id}/ads"
|
|
44
|
+
params = {
|
|
45
|
+
"fields": "id,name,adset_id,campaign_id,status,creative,created_time,updated_time,bid_amount,conversion_domain,tracking_specs",
|
|
46
|
+
"limit": limit
|
|
47
|
+
}
|
|
41
48
|
# Use campaign-specific endpoint if campaign_id is provided
|
|
42
|
-
|
|
49
|
+
elif campaign_id:
|
|
43
50
|
endpoint = f"{campaign_id}/ads"
|
|
44
51
|
params = {
|
|
45
52
|
"fields": "id,name,adset_id,campaign_id,status,creative,created_time,updated_time,bid_amount,conversion_domain,tracking_specs",
|
|
46
53
|
"limit": limit
|
|
47
54
|
}
|
|
48
|
-
# Adset ID can still be used to filter within the campaign
|
|
49
|
-
if adset_id:
|
|
50
|
-
params["adset_id"] = adset_id
|
|
51
55
|
else:
|
|
52
|
-
# Default to account-level endpoint if no
|
|
56
|
+
# Default to account-level endpoint if no specific filters
|
|
53
57
|
endpoint = f"{account_id}/ads"
|
|
54
58
|
params = {
|
|
55
59
|
"fields": "id,name,adset_id,campaign_id,status,creative,created_time,updated_time,bid_amount,conversion_domain,tracking_specs",
|
|
56
60
|
"limit": limit
|
|
57
61
|
}
|
|
58
|
-
# Adset ID can filter at the account level if no campaign specified
|
|
59
|
-
if adset_id:
|
|
60
|
-
params["adset_id"] = adset_id
|
|
61
62
|
|
|
62
63
|
data = await make_api_request(endpoint, access_token, params)
|
|
63
64
|
|
|
@@ -231,13 +231,22 @@ class HTTPTransportTester:
|
|
|
231
231
|
)
|
|
232
232
|
all_results[scenario["name"]] = results
|
|
233
233
|
|
|
234
|
+
# Run specific get_ads filtering tests
|
|
235
|
+
print("\n🧪 Testing get_ads filtering functionality")
|
|
236
|
+
print("="*50)
|
|
237
|
+
ads_filter_results = self.test_get_ads_filtering()
|
|
238
|
+
all_results["get_ads_filtering"] = ads_filter_results
|
|
239
|
+
|
|
234
240
|
# Summary
|
|
235
241
|
print("\n🏁 TEST SUITE COMPLETED")
|
|
236
242
|
print("="*30)
|
|
237
243
|
|
|
238
244
|
all_passed = True
|
|
239
245
|
for scenario_name, results in all_results.items():
|
|
240
|
-
|
|
246
|
+
if isinstance(results, dict):
|
|
247
|
+
scenario_success = all(results.values())
|
|
248
|
+
else:
|
|
249
|
+
scenario_success = results
|
|
241
250
|
status = "✅ SUCCESS" if scenario_success else "❌ FAILED"
|
|
242
251
|
print(f"{scenario_name}: {status}")
|
|
243
252
|
if not scenario_success:
|
|
@@ -250,10 +259,72 @@ class HTTPTransportTester:
|
|
|
250
259
|
print(" • MCP protocol compliance: Complete")
|
|
251
260
|
print(" • Authentication integration: Working")
|
|
252
261
|
print(" • All tools accessible via HTTP")
|
|
262
|
+
print(" • get_ads filtering: Working correctly")
|
|
253
263
|
print(" • Ready for production use")
|
|
254
264
|
|
|
255
265
|
return all_passed
|
|
256
266
|
|
|
267
|
+
def test_get_ads_filtering(self) -> Dict[str, bool]:
|
|
268
|
+
"""Test get_ads function with different filtering parameters"""
|
|
269
|
+
results = {}
|
|
270
|
+
|
|
271
|
+
# Test with basic auth headers for these tests
|
|
272
|
+
auth_headers = {"Authorization": "Bearer test_pipeboard_token_12345"}
|
|
273
|
+
|
|
274
|
+
# Test 1: get_ads without filters (should use account endpoint)
|
|
275
|
+
print("🔍 Testing get_ads without filters")
|
|
276
|
+
result1 = self.test_tool_call("get_ads", {
|
|
277
|
+
"account_id": "act_123456789",
|
|
278
|
+
"limit": 5
|
|
279
|
+
}, auth_headers)
|
|
280
|
+
results["no_filters"] = result1["success"]
|
|
281
|
+
if result1["success"]:
|
|
282
|
+
print("✅ get_ads without filters successful")
|
|
283
|
+
else:
|
|
284
|
+
print(f"❌ get_ads without filters failed: {result1.get('text', 'Unknown error')}")
|
|
285
|
+
|
|
286
|
+
# Test 2: get_ads with campaign_id filter (should use campaign endpoint)
|
|
287
|
+
print("🔍 Testing get_ads with campaign_id filter")
|
|
288
|
+
result2 = self.test_tool_call("get_ads", {
|
|
289
|
+
"account_id": "act_123456789",
|
|
290
|
+
"campaign_id": "123456789012345",
|
|
291
|
+
"limit": 5
|
|
292
|
+
}, auth_headers)
|
|
293
|
+
results["campaign_filter"] = result2["success"]
|
|
294
|
+
if result2["success"]:
|
|
295
|
+
print("✅ get_ads with campaign_id filter successful")
|
|
296
|
+
else:
|
|
297
|
+
print(f"❌ get_ads with campaign_id filter failed: {result2.get('text', 'Unknown error')}")
|
|
298
|
+
|
|
299
|
+
# Test 3: get_ads with adset_id filter (should use adset endpoint)
|
|
300
|
+
print("🔍 Testing get_ads with adset_id filter")
|
|
301
|
+
result3 = self.test_tool_call("get_ads", {
|
|
302
|
+
"account_id": "act_123456789",
|
|
303
|
+
"adset_id": "120228975637820183",
|
|
304
|
+
"limit": 5
|
|
305
|
+
}, auth_headers)
|
|
306
|
+
results["adset_filter"] = result3["success"]
|
|
307
|
+
if result3["success"]:
|
|
308
|
+
print("✅ get_ads with adset_id filter successful")
|
|
309
|
+
else:
|
|
310
|
+
print(f"❌ get_ads with adset_id filter failed: {result3.get('text', 'Unknown error')}")
|
|
311
|
+
|
|
312
|
+
# Test 4: get_ads with both campaign_id and adset_id (adset_id should take priority)
|
|
313
|
+
print("🔍 Testing get_ads with both campaign_id and adset_id (adset_id priority)")
|
|
314
|
+
result4 = self.test_tool_call("get_ads", {
|
|
315
|
+
"account_id": "act_123456789",
|
|
316
|
+
"campaign_id": "123456789012345",
|
|
317
|
+
"adset_id": "120228975637820183",
|
|
318
|
+
"limit": 5
|
|
319
|
+
}, auth_headers)
|
|
320
|
+
results["priority_test"] = result4["success"]
|
|
321
|
+
if result4["success"]:
|
|
322
|
+
print("✅ get_ads priority test successful")
|
|
323
|
+
else:
|
|
324
|
+
print(f"❌ get_ads priority test failed: {result4.get('text', 'Unknown error')}")
|
|
325
|
+
|
|
326
|
+
return results
|
|
327
|
+
|
|
257
328
|
|
|
258
329
|
def main():
|
|
259
330
|
"""Main test execution"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|