create_ad_creative
Create a single-text ad creative for Facebook or Instagram by providing a page ID and either video data or link data with image hash, URL, and message. Supports Instagram placements via optional user ID.
Instructions
WRITE: Create a single-text ad creative from an object_story_spec. Pass page_id plus ONE of: video_data (for video ads — needs video_id from upload_video), link_data (for image / link ads — needs image_hash from upload_image + link + message). If the Page is not linked to Instagram, pass instagram_user_id from get_pbia() to enable IG placements.
Note: image hashes are per-ad-account in Meta — a hash uploaded on account A is NOT valid on account B. Re-upload to each target account.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| ad_account_id | Yes | 'act_123' or '123' | |
| name | Yes | ||
| page_id | Yes | Facebook Page ID (the advertiser) | |
| instagram_user_id | No | Instagram actor ID or PBIA id (from get_pbia). Optional. | |
| video_id | No | From upload_video | |
| image_hash | No | From upload_image | |
| message | No | Primary text / body copy | |
| title | No | Headline for link_data | |
| link | No | Landing page URL (for link_data) | |
| call_to_action | No | e.g. {type: 'SHOP_NOW', value: {link: 'https://...'}} | |
| description | No | ||
| url_tags | No | UTM tracking params | |
| thumbnail_url | No |
Implementation Reference
- src/tools/creatives.ts:77-112 (handler)The handler function for 'create_ad_creative'. It builds an object_story_spec with either video_data (if video_id provided) or link_data (if image_hash provided), then POSTs to /{ad_account_id}/adcreatives via metaPost.
handler: async (args) => { const story: Record<string, unknown> = { page_id: args.page_id }; if (args.instagram_user_id) story.instagram_user_id = args.instagram_user_id; if (args.video_id) { const video_data: Record<string, unknown> = { video_id: args.video_id }; if (args.message) video_data.message = args.message; if (args.title) video_data.title = args.title; if (args.call_to_action) video_data.call_to_action = args.call_to_action; if (args.thumbnail_url) video_data.image_url = args.thumbnail_url; story.video_data = video_data; } else if (args.image_hash) { const link_data: Record<string, unknown> = { image_hash: args.image_hash }; if (args.link) link_data.link = args.link; if (args.message) link_data.message = args.message; if (args.title) link_data.name = args.title; if (args.description) link_data.description = args.description; if (args.call_to_action) link_data.call_to_action = args.call_to_action; story.link_data = link_data; } else { throw new Error( "create_ad_creative needs either video_id (video ad) or image_hash + link (image/link ad).", ); } const body: Record<string, unknown> = { name: args.name, object_story_spec: story, }; if (args.url_tags) body.url_tags = args.url_tags; return metaPost( `/${toAdAccountPath(String(args.ad_account_id))}/adcreatives`, body, ); }, - src/tools/creatives.ts:54-76 (schema)Input schema for create_ad_creative defined with Zod. Validates ad_account_id, name, page_id, and optional fields: instagram_user_id, video_id, image_hash, message, title, link, call_to_action, description, url_tags, thumbnail_url.
inputSchema: { ad_account_id: z.string().describe("'act_123' or '123'"), name: z.string().min(1), page_id: z.string().describe("Facebook Page ID (the advertiser)"), instagram_user_id: z .string() .optional() .describe("Instagram actor ID or PBIA id (from get_pbia). Optional."), video_id: z.string().optional().describe("From upload_video"), image_hash: z.string().optional().describe("From upload_image"), message: z.string().optional().describe("Primary text / body copy"), title: z.string().optional().describe("Headline for link_data"), link: z.string().url().optional().describe("Landing page URL (for link_data)"), call_to_action: z .record(z.unknown()) .optional() .describe( "e.g. {type: 'SHOP_NOW', value: {link: 'https://...'}}", ), description: z.string().optional(), url_tags: z.string().optional().describe("UTM tracking params"), thumbnail_url: z.string().url().optional(), }, - src/index.ts:47-52 (registration)Registration of creativeTools (which includes create_ad_creative) in the allTools array, then registered via server.registerTool() in the stdio entrypoint.
const allTools: ToolDef[] = [ ...accountTools, ...campaignTools, ...adsetTools, ...adTools, ...creativeTools, - src/http.ts:30-41 (registration)Registration of creativeTools (which includes create_ad_creative) in the allTools array, then registered via server.registerTool() in the HTTP entrypoint.
const allTools: ToolDef[] = [ ...accountTools, ...campaignTools, ...adsetTools, ...adTools, ...creativeTools, ...mediaTools, ...insightsTools, ...bulkTools, ...pageTools, ...adsLibraryTools, ]; - src/tools/creatives.ts:5-7 (helper)Helper function toAdAccountPath used in the handler to normalize ad account IDs (ensures 'act_' prefix).
function toAdAccountPath(idOrActId: string): string { return idOrActId.startsWith("act_") ? idOrActId : `act_${idOrActId}`; }