meta-ads-mcp 0.7.6__tar.gz → 0.7.7__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 (64) hide show
  1. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/PKG-INFO +1 -1
  2. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/RELEASE.md +23 -10
  3. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/__init__.py +1 -1
  4. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/accounts.py +10 -0
  5. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/adsets.py +36 -6
  6. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/pyproject.toml +1 -1
  7. meta_ads_mcp-0.7.7/tests/test_dsa_beneficiary.py +597 -0
  8. meta_ads_mcp-0.7.7/tests/test_dsa_integration.py +380 -0
  9. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/.github/workflows/publish.yml +0 -0
  10. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/.github/workflows/test.yml +0 -0
  11. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/.gitignore +0 -0
  12. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/CUSTOM_META_APP.md +0 -0
  13. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/Dockerfile +0 -0
  14. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/LICENSE +0 -0
  15. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/LOCAL_INSTALLATION.md +0 -0
  16. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/META_API_NOTES.md +0 -0
  17. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/README.md +0 -0
  18. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/STREAMABLE_HTTP_SETUP.md +0 -0
  19. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/examples/README.md +0 -0
  20. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/examples/example_http_client.py +0 -0
  21. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/future_improvements.md +0 -0
  22. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/images/meta-ads-example.png +0 -0
  23. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_auth.sh +0 -0
  24. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/__main__.py +0 -0
  25. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/__init__.py +0 -0
  26. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/ads.py +0 -0
  27. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/ads_library.py +0 -0
  28. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/api.py +0 -0
  29. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/auth.py +0 -0
  30. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/authentication.py +0 -0
  31. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/budget_schedules.py +0 -0
  32. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/callback_server.py +0 -0
  33. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/campaigns.py +0 -0
  34. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/duplication.py +0 -0
  35. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/http_auth_integration.py +0 -0
  36. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/insights.py +0 -0
  37. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/openai_deep_research.py +0 -0
  38. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/pipeboard_auth.py +0 -0
  39. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/reports.py +0 -0
  40. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/resources.py +0 -0
  41. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/server.py +0 -0
  42. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/targeting.py +0 -0
  43. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/meta_ads_mcp/core/utils.py +0 -0
  44. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/requirements.txt +0 -0
  45. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/setup.py +0 -0
  46. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/smithery.yaml +0 -0
  47. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/README.md +0 -0
  48. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/README_REGRESSION_TESTS.md +0 -0
  49. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/__init__.py +0 -0
  50. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/conftest.py +0 -0
  51. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/test_account_search.py +0 -0
  52. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/test_budget_update.py +0 -0
  53. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/test_budget_update_e2e.py +0 -0
  54. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/test_duplication.py +0 -0
  55. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/test_duplication_regression.py +0 -0
  56. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/test_get_ad_creatives_fix.py +0 -0
  57. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/test_get_ad_image_regression.py +0 -0
  58. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/test_http_transport.py +0 -0
  59. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/test_insights_actions_and_values.py +0 -0
  60. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/test_integration_openai_mcp.py +0 -0
  61. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/test_openai.py +0 -0
  62. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/test_openai_mcp_deep_research.py +0 -0
  63. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/test_targeting.py +0 -0
  64. {meta_ads_mcp-0.7.6 → meta_ads_mcp-0.7.7}/tests/test_targeting_search_e2e.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meta-ads-mcp
3
- Version: 0.7.6
3
+ Version: 0.7.7
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
@@ -29,15 +29,27 @@ This repository uses GitHub Actions to automatically publish releases to PyPI. H
29
29
  git push origin main
30
30
  ```
31
31
 
32
- 3. **Create a GitHub release**:
33
- - Go to https://github.com/pipeboard-co/meta-ads-mcp/releases
34
- - Click "Create a new release"
35
- - Tag version: `v0.3.8` (must match the version in pyproject.toml)
36
- - Release title: `v0.3.8`
37
- - Add release notes describing what changed
38
- - Click "Publish release"
39
-
40
- 4. **Automatic deployment**:
32
+ 3. **Wait for build tests to pass** (optional):
33
+ ```bash
34
+ # Check the latest test workflow run
35
+ gh run list --workflow=test.yml --limit 1
36
+
37
+ # Get the run ID and wait for completion
38
+ RUN_ID=$(gh run list --workflow=test.yml --limit 1 --json databaseId --jq '.[0].databaseId')
39
+ gh run watch $RUN_ID
40
+ ```
41
+ Note: This only tests package building and installation, not the actual pytest tests.
42
+
43
+ 4. **Create a GitHub release**:
44
+ ```bash
45
+ gh release create 0.3.8 --title "0.3.8" --generate-notes
46
+ ```
47
+ This command will:
48
+ - Create a release with the specified version (no "v" prefix)
49
+ - Auto-generate release notes from commits
50
+ - Automatically trigger the GitHub Action for PyPI publishing
51
+
52
+ 5. **Automatic deployment**:
41
53
  - The GitHub Action will automatically trigger
42
54
  - It will build the package and publish to PyPI
43
55
  - Check the "Actions" tab to monitor progress
@@ -49,10 +61,11 @@ This repository uses GitHub Actions to automatically publish releases to PyPI. H
49
61
  - **Purpose**: Builds and publishes the package to PyPI
50
62
  - **Security**: Uses trusted publishing with OIDC tokens (no API keys needed)
51
63
 
52
- ### `test.yml` (if present)
64
+ ### `test.yml`
53
65
  - **Triggers**: On pushes and pull requests to main/master
54
66
  - **Purpose**: Tests package building and installation across Python versions
55
67
  - **Matrix**: Tests Python 3.10, 3.11, and 3.12
68
+ - **Note**: Does not run pytest tests, only validates package structure
56
69
 
57
70
  ## Manual Deployment
58
71
 
@@ -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.7.6"
10
+ __version__ = "0.7.7"
11
11
 
12
12
  __all__ = [
13
13
  'get_ad_accounts',
@@ -59,4 +59,14 @@ async def get_account_info(access_token: str = None, account_id: str = None) ->
59
59
 
60
60
  data = await make_api_request(endpoint, access_token, params)
61
61
 
62
+ # Add DSA requirement detection
63
+ if "business_country_code" in data:
64
+ european_countries = ["DE", "FR", "IT", "ES", "NL", "BE", "AT", "IE", "DK", "SE", "FI", "NO"]
65
+ if data["business_country_code"] in european_countries:
66
+ data["dsa_required"] = True
67
+ data["dsa_compliance_note"] = "This account is subject to European DSA (Digital Services Act) requirements"
68
+ else:
69
+ data["dsa_required"] = False
70
+ data["dsa_compliance_note"] = "This account is not subject to European DSA requirements"
71
+
62
72
  return json.dumps(data, indent=2)
@@ -73,7 +73,7 @@ async def get_adset_details(access_token: str = None, adset_id: str = None) -> s
73
73
  endpoint = f"{adset_id}"
74
74
  # Explicitly prioritize frequency_control_specs in the fields request
75
75
  params = {
76
- "fields": "id,name,campaign_id,status,frequency_control_specs{event,interval_days,max_frequency},daily_budget,lifetime_budget,targeting,bid_amount,bid_strategy,optimization_goal,billing_event,start_time,end_time,created_time,updated_time,attribution_spec,destination_type,promoted_object,pacing_type,budget_remaining"
76
+ "fields": "id,name,campaign_id,status,frequency_control_specs{event,interval_days,max_frequency},daily_budget,lifetime_budget,targeting,bid_amount,bid_strategy,optimization_goal,billing_event,start_time,end_time,created_time,updated_time,attribution_spec,destination_type,promoted_object,pacing_type,budget_remaining,dsa_beneficiary"
77
77
  }
78
78
 
79
79
  data = await make_api_request(endpoint, access_token, params)
@@ -103,6 +103,7 @@ async def create_adset(
103
103
  bid_strategy: str = None,
104
104
  start_time: str = None,
105
105
  end_time: str = None,
106
+ dsa_beneficiary: str = None,
106
107
  access_token: str = None
107
108
  ) -> str:
108
109
  """
@@ -123,6 +124,7 @@ async def create_adset(
123
124
  bid_strategy: Bid strategy (e.g., 'LOWEST_COST', 'LOWEST_COST_WITH_BID_CAP')
124
125
  start_time: Start time in ISO 8601 format (e.g., '2023-12-01T12:00:00-0800')
125
126
  end_time: End time in ISO 8601 format
127
+ dsa_beneficiary: DSA beneficiary (person/organization benefiting from ads) for European compliance
126
128
  access_token: Meta API access token (optional - will use cached token if not provided)
127
129
  """
128
130
  # Check required parameters
@@ -181,16 +183,44 @@ async def create_adset(
181
183
  if end_time:
182
184
  params["end_time"] = end_time
183
185
 
186
+ # Add DSA beneficiary if provided
187
+ if dsa_beneficiary:
188
+ params["dsa_beneficiary"] = dsa_beneficiary
189
+
184
190
  try:
185
191
  data = await make_api_request(endpoint, access_token, params, method="POST")
186
192
  return json.dumps(data, indent=2)
187
193
  except Exception as e:
188
194
  error_msg = str(e)
189
- return json.dumps({
190
- "error": "Failed to create ad set",
191
- "details": error_msg,
192
- "params_sent": params
193
- }, indent=2)
195
+
196
+ # Enhanced error handling for DSA beneficiary issues
197
+ if "permission" in error_msg.lower() or "insufficient" in error_msg.lower():
198
+ return json.dumps({
199
+ "error": "Insufficient permissions to set DSA beneficiary. Please ensure you have business_management permissions.",
200
+ "details": error_msg,
201
+ "params_sent": params,
202
+ "permission_required": True
203
+ }, indent=2)
204
+ elif "dsa_beneficiary" in error_msg.lower() and ("not supported" in error_msg.lower() or "parameter" in error_msg.lower()):
205
+ return json.dumps({
206
+ "error": "DSA beneficiary parameter not supported in this API version. Please set DSA beneficiary manually in Facebook Ads Manager.",
207
+ "details": error_msg,
208
+ "params_sent": params,
209
+ "manual_setup_required": True
210
+ }, indent=2)
211
+ elif "benefits from ads" in error_msg or "DSA beneficiary" in error_msg:
212
+ return json.dumps({
213
+ "error": "DSA beneficiary required for European compliance. Please provide the person or organization that benefits from ads in this ad set.",
214
+ "details": error_msg,
215
+ "params_sent": params,
216
+ "dsa_required": True
217
+ }, indent=2)
218
+ else:
219
+ return json.dumps({
220
+ "error": "Failed to create ad set",
221
+ "details": error_msg,
222
+ "params_sent": params
223
+ }, indent=2)
194
224
 
195
225
 
196
226
  @mcp_server.tool()
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "meta-ads-mcp"
7
- version = "0.7.6"
7
+ version = "0.7.7"
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"