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.
Files changed (50) hide show
  1. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/PKG-INFO +1 -1
  2. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/__init__.py +1 -1
  3. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/ads.py +9 -8
  4. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/pyproject.toml +1 -1
  5. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/tests/test_http_transport.py +72 -1
  6. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/.github/workflows/publish.yml +0 -0
  7. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/.github/workflows/test.yml +0 -0
  8. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/.gitignore +0 -0
  9. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/CUSTOM_META_APP.md +0 -0
  10. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/Dockerfile +0 -0
  11. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/LICENSE +0 -0
  12. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/LOCAL_INSTALLATION.md +0 -0
  13. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/META_API_NOTES.md +0 -0
  14. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/README.md +0 -0
  15. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/RELEASE.md +0 -0
  16. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/STREAMABLE_HTTP_SETUP.md +0 -0
  17. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/examples/README.md +0 -0
  18. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/examples/example_http_client.py +0 -0
  19. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/future_improvements.md +0 -0
  20. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/images/meta-ads-example.png +0 -0
  21. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_auth.sh +0 -0
  22. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/__main__.py +0 -0
  23. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/__init__.py +0 -0
  24. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/accounts.py +0 -0
  25. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/ads_library.py +0 -0
  26. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/adsets.py +0 -0
  27. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/api.py +0 -0
  28. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/auth.py +0 -0
  29. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/authentication.py +0 -0
  30. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/budget_schedules.py +0 -0
  31. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/callback_server.py +0 -0
  32. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/campaigns.py +0 -0
  33. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/duplication.py +0 -0
  34. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/http_auth_integration.py +0 -0
  35. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/insights.py +0 -0
  36. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/pipeboard_auth.py +0 -0
  37. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/reports.py +0 -0
  38. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/resources.py +0 -0
  39. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/server.py +0 -0
  40. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/meta_ads_mcp/core/utils.py +0 -0
  41. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/requirements.txt +0 -0
  42. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/setup.py +0 -0
  43. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/smithery.yaml +0 -0
  44. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/tests/README.md +0 -0
  45. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/tests/README_REGRESSION_TESTS.md +0 -0
  46. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/tests/__init__.py +0 -0
  47. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/tests/conftest.py +0 -0
  48. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/tests/test_duplication.py +0 -0
  49. {meta_ads_mcp-0.4.2 → meta_ads_mcp-0.4.3}/tests/test_duplication_regression.py +0 -0
  50. {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.2
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
@@ -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.4.2"
10
+ __version__ = "0.4.3"
11
11
 
12
12
  __all__ = [
13
13
  'get_ad_accounts',
@@ -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
- if campaign_id:
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 campaign_id
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
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "meta-ads-mcp"
7
- version = "0.4.2"
7
+ version = "0.4.3"
8
8
  description = "Model Context Protocol (MCP) plugin for interacting with Meta Ads API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -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
- scenario_success = all(results.values())
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