@mcp_server.tool()
@meta_api_tool
async def create_ad(
account_id: str,
name: str,
adset_id: str,
creative_id: str,
status: str = "PAUSED",
bid_amount: Optional[int] = None,
tracking_specs: Optional[List[Dict[str, Any]]] = None,
access_token: Optional[str] = None
) -> str:
"""
Create a new ad with an existing creative.
Args:
account_id: Meta Ads account ID (format: act_XXXXXXXXX)
name: Ad name
adset_id: Ad set ID where this ad will be placed
creative_id: ID of an existing creative to use
status: Initial ad status (default: PAUSED)
bid_amount: Optional bid amount in account currency (in cents)
tracking_specs: Optional tracking specifications (e.g., for pixel events).
Example: [{"action.type":"offsite_conversion","fb_pixel":["YOUR_PIXEL_ID"]}]
access_token: Meta API access token (optional - will use cached token if not provided)
Note:
Dynamic Creative creatives require the parent ad set to have `is_dynamic_creative=true`.
Otherwise, ad creation will fail with error_subcode 1885998.
"""
# Check required parameters
if not account_id:
return json.dumps({"error": "No account ID provided"}, indent=2)
if not name:
return json.dumps({"error": "No ad name provided"}, indent=2)
if not adset_id:
return json.dumps({"error": "No ad set ID provided"}, indent=2)
if not creative_id:
return json.dumps({"error": "No creative ID provided"}, indent=2)
endpoint = f"{account_id}/ads"
params = {
"name": name,
"adset_id": adset_id,
"creative": {"creative_id": creative_id},
"status": status
}
# Add bid amount if provided
if bid_amount is not None:
params["bid_amount"] = str(bid_amount)
# Add tracking specs if provided
if tracking_specs is not None:
params["tracking_specs"] = json.dumps(tracking_specs) # Needs to be JSON encoded string
try:
data = await make_api_request(endpoint, access_token, params, method="POST")
return json.dumps(data, indent=2)
except Exception as e:
error_msg = str(e)
return json.dumps({
"error": "Failed to create ad",
"details": error_msg,
"params_sent": params
}, indent=2)