meta-ads-mcp 0.7.4__py3-none-any.whl → 0.7.5__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/adsets.py +12 -2
- meta_ads_mcp/core/campaigns.py +77 -24
- {meta_ads_mcp-0.7.4.dist-info → meta_ads_mcp-0.7.5.dist-info}/METADATA +1 -1
- {meta_ads_mcp-0.7.4.dist-info → meta_ads_mcp-0.7.5.dist-info}/RECORD +8 -8
- {meta_ads_mcp-0.7.4.dist-info → meta_ads_mcp-0.7.5.dist-info}/WHEEL +0 -0
- {meta_ads_mcp-0.7.4.dist-info → meta_ads_mcp-0.7.5.dist-info}/entry_points.txt +0 -0
- {meta_ads_mcp-0.7.4.dist-info → meta_ads_mcp-0.7.5.dist-info}/licenses/LICENSE +0 -0
meta_ads_mcp/__init__.py
CHANGED
meta_ads_mcp/core/adsets.py
CHANGED
|
@@ -197,9 +197,10 @@ async def create_adset(
|
|
|
197
197
|
@meta_api_tool
|
|
198
198
|
async def update_adset(adset_id: str, frequency_control_specs: List[Dict[str, Any]] = None, bid_strategy: str = None,
|
|
199
199
|
bid_amount: int = None, status: str = None, targeting: Dict[str, Any] = None,
|
|
200
|
-
optimization_goal: str = None,
|
|
200
|
+
optimization_goal: str = None, daily_budget = None, lifetime_budget = None,
|
|
201
|
+
access_token: str = None) -> str:
|
|
201
202
|
"""
|
|
202
|
-
Update an ad set with new settings including frequency caps.
|
|
203
|
+
Update an ad set with new settings including frequency caps and budgets.
|
|
203
204
|
|
|
204
205
|
Args:
|
|
205
206
|
adset_id: Meta Ads ad set ID
|
|
@@ -211,6 +212,8 @@ async def update_adset(adset_id: str, frequency_control_specs: List[Dict[str, An
|
|
|
211
212
|
targeting: Complete targeting specifications (will replace existing targeting)
|
|
212
213
|
(e.g. {"targeting_automation":{"advantage_audience":1}, "geo_locations": {"countries": ["US"]}})
|
|
213
214
|
optimization_goal: Conversion optimization goal (e.g., 'LINK_CLICKS', 'CONVERSIONS', 'APP_INSTALLS', etc.)
|
|
215
|
+
daily_budget: Daily budget in account currency (in cents) as a string
|
|
216
|
+
lifetime_budget: Lifetime budget in account currency (in cents) as a string
|
|
214
217
|
access_token: Meta API access token (optional - will use cached token if not provided)
|
|
215
218
|
"""
|
|
216
219
|
if not adset_id:
|
|
@@ -240,6 +243,13 @@ async def update_adset(adset_id: str, frequency_control_specs: List[Dict[str, An
|
|
|
240
243
|
else:
|
|
241
244
|
params['targeting'] = targeting # Already a string
|
|
242
245
|
|
|
246
|
+
# Add budget parameters if provided
|
|
247
|
+
if daily_budget is not None:
|
|
248
|
+
params['daily_budget'] = str(daily_budget)
|
|
249
|
+
|
|
250
|
+
if lifetime_budget is not None:
|
|
251
|
+
params['lifetime_budget'] = str(lifetime_budget)
|
|
252
|
+
|
|
243
253
|
if not params:
|
|
244
254
|
return json.dumps({"error": "No update parameters provided"}, indent=2)
|
|
245
255
|
|
meta_ads_mcp/core/campaigns.py
CHANGED
|
@@ -99,7 +99,8 @@ async def create_campaign(
|
|
|
99
99
|
bid_cap = None,
|
|
100
100
|
spend_cap = None,
|
|
101
101
|
campaign_budget_optimization: bool = None,
|
|
102
|
-
ab_test_control_setups: Optional[List[Dict[str, Any]]] = None
|
|
102
|
+
ab_test_control_setups: Optional[List[Dict[str, Any]]] = None,
|
|
103
|
+
use_adset_level_budgets: bool = False
|
|
103
104
|
) -> str:
|
|
104
105
|
"""
|
|
105
106
|
Create a new campaign in a Meta Ads account.
|
|
@@ -111,14 +112,15 @@ async def create_campaign(
|
|
|
111
112
|
objective: Campaign objective. Validates ad objectives. enum{BRAND_AWARENESS, LEAD_GENERATION, LINK_CLICKS, CONVERSIONS, OUTCOME_TRAFFIC, etc.}.
|
|
112
113
|
status: Initial campaign status (default: PAUSED)
|
|
113
114
|
special_ad_categories: List of special ad categories if applicable
|
|
114
|
-
daily_budget: Daily budget in account currency (in cents) as a string
|
|
115
|
-
lifetime_budget: Lifetime budget in account currency (in cents) as a string
|
|
115
|
+
daily_budget: Daily budget in account currency (in cents) as a string (only used if use_adset_level_budgets=False)
|
|
116
|
+
lifetime_budget: Lifetime budget in account currency (in cents) as a string (only used if use_adset_level_budgets=False)
|
|
116
117
|
buying_type: Buying type (e.g., 'AUCTION')
|
|
117
118
|
bid_strategy: Bid strategy (e.g., 'LOWEST_COST', 'LOWEST_COST_WITH_BID_CAP', 'COST_CAP')
|
|
118
119
|
bid_cap: Bid cap in account currency (in cents) as a string
|
|
119
120
|
spend_cap: Spending limit for the campaign in account currency (in cents) as a string
|
|
120
|
-
campaign_budget_optimization: Whether to enable campaign budget optimization
|
|
121
|
+
campaign_budget_optimization: Whether to enable campaign budget optimization (only used if use_adset_level_budgets=False)
|
|
121
122
|
ab_test_control_setups: Settings for A/B testing (e.g., [{"name":"Creative A", "ad_format":"SINGLE_IMAGE"}])
|
|
123
|
+
use_adset_level_budgets: If True, budgets will be set at the ad set level instead of campaign level (default: False)
|
|
122
124
|
"""
|
|
123
125
|
# Check required parameters
|
|
124
126
|
if not account_id:
|
|
@@ -134,8 +136,8 @@ async def create_campaign(
|
|
|
134
136
|
if special_ad_categories is None:
|
|
135
137
|
special_ad_categories = []
|
|
136
138
|
|
|
137
|
-
# For this example, we'll add a fixed daily budget if none is provided
|
|
138
|
-
if not daily_budget and not lifetime_budget:
|
|
139
|
+
# For this example, we'll add a fixed daily budget if none is provided and we're not using ad set level budgets
|
|
140
|
+
if not daily_budget and not lifetime_budget and not use_adset_level_budgets:
|
|
139
141
|
daily_budget = "1000" # Default to $10 USD
|
|
140
142
|
|
|
141
143
|
endpoint = f"{account_id}/campaigns"
|
|
@@ -147,12 +149,17 @@ async def create_campaign(
|
|
|
147
149
|
"special_ad_categories": json.dumps(special_ad_categories) # Properly format as JSON string
|
|
148
150
|
}
|
|
149
151
|
|
|
150
|
-
#
|
|
151
|
-
if
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
152
|
+
# Only set campaign-level budgets if we're not using ad set level budgets
|
|
153
|
+
if not use_adset_level_budgets:
|
|
154
|
+
# Convert budget values to strings if they aren't already
|
|
155
|
+
if daily_budget is not None:
|
|
156
|
+
params["daily_budget"] = str(daily_budget)
|
|
157
|
+
|
|
158
|
+
if lifetime_budget is not None:
|
|
159
|
+
params["lifetime_budget"] = str(lifetime_budget)
|
|
160
|
+
|
|
161
|
+
if campaign_budget_optimization is not None:
|
|
162
|
+
params["campaign_budget_optimization"] = "true" if campaign_budget_optimization else "false"
|
|
156
163
|
|
|
157
164
|
# Add new parameters
|
|
158
165
|
if buying_type:
|
|
@@ -167,14 +174,17 @@ async def create_campaign(
|
|
|
167
174
|
if spend_cap is not None:
|
|
168
175
|
params["spend_cap"] = str(spend_cap)
|
|
169
176
|
|
|
170
|
-
if campaign_budget_optimization is not None:
|
|
171
|
-
params["campaign_budget_optimization"] = "true" if campaign_budget_optimization else "false"
|
|
172
|
-
|
|
173
177
|
if ab_test_control_setups:
|
|
174
178
|
params["ab_test_control_setups"] = json.dumps(ab_test_control_setups)
|
|
175
179
|
|
|
176
180
|
try:
|
|
177
181
|
data = await make_api_request(endpoint, access_token, params, method="POST")
|
|
182
|
+
|
|
183
|
+
# Add a note about budget strategy if using ad set level budgets
|
|
184
|
+
if use_adset_level_budgets:
|
|
185
|
+
data["budget_strategy"] = "ad_set_level"
|
|
186
|
+
data["note"] = "Campaign created with ad set level budgets. Set budgets when creating ad sets within this campaign."
|
|
187
|
+
|
|
178
188
|
return json.dumps(data, indent=2)
|
|
179
189
|
except Exception as e:
|
|
180
190
|
error_msg = str(e)
|
|
@@ -200,7 +210,7 @@ async def update_campaign(
|
|
|
200
210
|
spend_cap = None,
|
|
201
211
|
campaign_budget_optimization: bool = None,
|
|
202
212
|
objective: str = None, # Add objective if it's updatable
|
|
203
|
-
# Add other updatable fields as needed based on API docs
|
|
213
|
+
use_adset_level_budgets: bool = None, # Add other updatable fields as needed based on API docs
|
|
204
214
|
) -> str:
|
|
205
215
|
"""
|
|
206
216
|
Update an existing campaign in a Meta Ads account.
|
|
@@ -211,13 +221,16 @@ async def update_campaign(
|
|
|
211
221
|
name: New campaign name
|
|
212
222
|
status: New campaign status (e.g., 'ACTIVE', 'PAUSED')
|
|
213
223
|
special_ad_categories: List of special ad categories if applicable
|
|
214
|
-
daily_budget: New daily budget in account currency (in cents) as a string
|
|
215
|
-
|
|
224
|
+
daily_budget: New daily budget in account currency (in cents) as a string.
|
|
225
|
+
Set to empty string "" to remove the daily budget.
|
|
226
|
+
lifetime_budget: New lifetime budget in account currency (in cents) as a string.
|
|
227
|
+
Set to empty string "" to remove the lifetime budget.
|
|
216
228
|
bid_strategy: New bid strategy
|
|
217
229
|
bid_cap: New bid cap in account currency (in cents) as a string
|
|
218
230
|
spend_cap: New spending limit for the campaign in account currency (in cents) as a string
|
|
219
231
|
campaign_budget_optimization: Enable/disable campaign budget optimization
|
|
220
232
|
objective: New campaign objective (Note: May not always be updatable)
|
|
233
|
+
use_adset_level_budgets: If True, removes campaign-level budgets to switch to ad set level budgets
|
|
221
234
|
"""
|
|
222
235
|
if not campaign_id:
|
|
223
236
|
return json.dumps({"error": "No campaign ID provided"}, indent=2)
|
|
@@ -235,18 +248,52 @@ async def update_campaign(
|
|
|
235
248
|
# Note: Updating special_ad_categories might have specific API rules or might not be allowed after creation.
|
|
236
249
|
# The API might require an empty list `[]` to clear categories. Check Meta Docs.
|
|
237
250
|
params["special_ad_categories"] = json.dumps(special_ad_categories)
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
if
|
|
241
|
-
|
|
251
|
+
|
|
252
|
+
# Handle budget parameters based on use_adset_level_budgets setting
|
|
253
|
+
if use_adset_level_budgets is not None:
|
|
254
|
+
if use_adset_level_budgets:
|
|
255
|
+
# Remove campaign-level budgets when switching to ad set level budgets
|
|
256
|
+
params["daily_budget"] = ""
|
|
257
|
+
params["lifetime_budget"] = ""
|
|
258
|
+
if campaign_budget_optimization is not None:
|
|
259
|
+
params["campaign_budget_optimization"] = "false"
|
|
260
|
+
else:
|
|
261
|
+
# If switching back to campaign-level budgets, use the provided budget values
|
|
262
|
+
if daily_budget is not None:
|
|
263
|
+
if daily_budget == "":
|
|
264
|
+
params["daily_budget"] = ""
|
|
265
|
+
else:
|
|
266
|
+
params["daily_budget"] = str(daily_budget)
|
|
267
|
+
if lifetime_budget is not None:
|
|
268
|
+
if lifetime_budget == "":
|
|
269
|
+
params["lifetime_budget"] = ""
|
|
270
|
+
else:
|
|
271
|
+
params["lifetime_budget"] = str(lifetime_budget)
|
|
272
|
+
if campaign_budget_optimization is not None:
|
|
273
|
+
params["campaign_budget_optimization"] = "true" if campaign_budget_optimization else "false"
|
|
274
|
+
else:
|
|
275
|
+
# Normal budget updates when not changing budget strategy
|
|
276
|
+
if daily_budget is not None:
|
|
277
|
+
# To remove budget, set to empty string
|
|
278
|
+
if daily_budget == "":
|
|
279
|
+
params["daily_budget"] = ""
|
|
280
|
+
else:
|
|
281
|
+
params["daily_budget"] = str(daily_budget)
|
|
282
|
+
if lifetime_budget is not None:
|
|
283
|
+
# To remove budget, set to empty string
|
|
284
|
+
if lifetime_budget == "":
|
|
285
|
+
params["lifetime_budget"] = ""
|
|
286
|
+
else:
|
|
287
|
+
params["lifetime_budget"] = str(lifetime_budget)
|
|
288
|
+
if campaign_budget_optimization is not None:
|
|
289
|
+
params["campaign_budget_optimization"] = "true" if campaign_budget_optimization else "false"
|
|
290
|
+
|
|
242
291
|
if bid_strategy is not None:
|
|
243
292
|
params["bid_strategy"] = bid_strategy
|
|
244
293
|
if bid_cap is not None:
|
|
245
294
|
params["bid_cap"] = str(bid_cap)
|
|
246
295
|
if spend_cap is not None:
|
|
247
296
|
params["spend_cap"] = str(spend_cap)
|
|
248
|
-
if campaign_budget_optimization is not None:
|
|
249
|
-
params["campaign_budget_optimization"] = "true" if campaign_budget_optimization else "false"
|
|
250
297
|
if objective is not None:
|
|
251
298
|
params["objective"] = objective # Caution: Objective changes might reset learning or be restricted
|
|
252
299
|
|
|
@@ -256,6 +303,12 @@ async def update_campaign(
|
|
|
256
303
|
try:
|
|
257
304
|
# Use POST method for updates as per Meta API documentation
|
|
258
305
|
data = await make_api_request(endpoint, access_token, params, method="POST")
|
|
306
|
+
|
|
307
|
+
# Add a note about budget strategy if switching to ad set level budgets
|
|
308
|
+
if use_adset_level_budgets is not None and use_adset_level_budgets:
|
|
309
|
+
data["budget_strategy"] = "ad_set_level"
|
|
310
|
+
data["note"] = "Campaign updated to use ad set level budgets. Set budgets when creating ad sets within this campaign."
|
|
311
|
+
|
|
259
312
|
return json.dumps(data, indent=2)
|
|
260
313
|
except Exception as e:
|
|
261
314
|
error_msg = str(e)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meta-ads-mcp
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.5
|
|
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,16 +1,16 @@
|
|
|
1
|
-
meta_ads_mcp/__init__.py,sha256=
|
|
1
|
+
meta_ads_mcp/__init__.py,sha256=6q-iZb-0TjRTI3Pz2mdCt8mGubBzhZbdVUCT601s5KY,1492
|
|
2
2
|
meta_ads_mcp/__main__.py,sha256=XaQt3iXftG_7f0Zu7Wop9SeFgrD2WBn0EQOaPMc27d8,207
|
|
3
3
|
meta_ads_mcp/core/__init__.py,sha256=6nYdue6yRepkt6JTAoPGhGbS51qfDSvmczRrDwYOG6A,1709
|
|
4
4
|
meta_ads_mcp/core/accounts.py,sha256=Nmp7lPxO9wmq25jWV7_H0LIqnEbBhpCVBlLGW2HUaq0,2277
|
|
5
5
|
meta_ads_mcp/core/ads.py,sha256=aaK70mgfhBJRXr4cdkKag5mjYzvHuHpRttJvTMzPk4Y,36156
|
|
6
6
|
meta_ads_mcp/core/ads_library.py,sha256=BBGVbtjO5eFV42iiY3XPU-wIV8HupzUKpHgPBrydSvU,3232
|
|
7
|
-
meta_ads_mcp/core/adsets.py,sha256=
|
|
7
|
+
meta_ads_mcp/core/adsets.py,sha256=yyOS5k_DPlwZERJmzUf3UBVwvE9KsA9E9gdMyHP2ZBY,10870
|
|
8
8
|
meta_ads_mcp/core/api.py,sha256=aAzM6Q75VQOFXtr5D-mDmBRhxWK4wsiODsJYnR3mpDI,14994
|
|
9
9
|
meta_ads_mcp/core/auth.py,sha256=H-0s0O2fLo14rmi81Hh5S64pyRl1HS7dm9Q_8UCa3Jg,21622
|
|
10
10
|
meta_ads_mcp/core/authentication.py,sha256=-AJxa3a5ZshRCvmJThBaNwCAJ1D2_qOgUkvu539c_MY,10159
|
|
11
11
|
meta_ads_mcp/core/budget_schedules.py,sha256=UxseExsvKAiPwfDCY9aycT4kys4xqeNytyq-yyDOxrs,2901
|
|
12
12
|
meta_ads_mcp/core/callback_server.py,sha256=LIAJv9DW--83kdZ7VWWZal8xEprYjRZ8iug4rMczYbQ,9372
|
|
13
|
-
meta_ads_mcp/core/campaigns.py,sha256=
|
|
13
|
+
meta_ads_mcp/core/campaigns.py,sha256=0yDVgi7rN4eMQk1_w0A2vnoXd8y0t8R77Ji4gna1Gj4,14030
|
|
14
14
|
meta_ads_mcp/core/duplication.py,sha256=UUmTDFx9o5ZsPQG2Rb9c4ZyuKUVN3FfTjebfTIHHdo4,18984
|
|
15
15
|
meta_ads_mcp/core/http_auth_integration.py,sha256=lGpKhfzJcyWugBcYEvypY-qnlt-3UDBLqh7xAUH0DGw,12473
|
|
16
16
|
meta_ads_mcp/core/insights.py,sha256=U7KYdWQpGcdykE1WUtdJdYR3VTwKrXUzIzCREwWbf48,2599
|
|
@@ -21,8 +21,8 @@ meta_ads_mcp/core/resources.py,sha256=-zIIfZulpo76vcKv6jhAlQq91cR2SZ3cjYZt3ek3x0
|
|
|
21
21
|
meta_ads_mcp/core/server.py,sha256=WhbAag7xdhbGcp7rnU4sKhqXJ8Slapa_ba3T23Yp_2U,17889
|
|
22
22
|
meta_ads_mcp/core/targeting.py,sha256=3HW1qirEdwaQurlBZGenbIwawcb5J06ghJKRfgu9ZEs,6318
|
|
23
23
|
meta_ads_mcp/core/utils.py,sha256=ofKUhyo-5SZoJVuBeTVFPPQCffk0UKpwmDMrd8qQxNc,8715
|
|
24
|
-
meta_ads_mcp-0.7.
|
|
25
|
-
meta_ads_mcp-0.7.
|
|
26
|
-
meta_ads_mcp-0.7.
|
|
27
|
-
meta_ads_mcp-0.7.
|
|
28
|
-
meta_ads_mcp-0.7.
|
|
24
|
+
meta_ads_mcp-0.7.5.dist-info/METADATA,sha256=42uw2yEhgxLqqHEOhAqgiPqfwNYvLjR6qL7rzGYTaAk,20409
|
|
25
|
+
meta_ads_mcp-0.7.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
26
|
+
meta_ads_mcp-0.7.5.dist-info/entry_points.txt,sha256=Dv2RkoBjRJBqj6CyhwqGIiwPCD-SCL1-7B9-zmVRuv0,57
|
|
27
|
+
meta_ads_mcp-0.7.5.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
28
|
+
meta_ads_mcp-0.7.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|