Before you begin
You need a connected agent, a Write workspace key for the intended workspace, and the required creative and proposal permissions. Readget_account_state to confirm scope. A person must select the source ad; obtain the selected asset ID from the account’s creative library.
Check the workspace’s action policy. Use Ask for this walkthrough so you can review the proposal before execution. In Full, an allowed proposal can queue automatically; asking the agent to stop after submission does not prevent that execution. These creative tools cannot activate the copy. Canonical pause, resume, and daily-budget changes use separate governed proposals.
Creative tool flow
The anonymous MCP sandbox has no creative tools. Use the authenticated production connection for this workflow. Reading the library contacts Meta; submitting the proposal writes to Plainrouter and performs account-bound provider reads. It does not itself create the copied Meta ad.
Example: propose a paused creative variant
The request examples below contain arguments for the named MCP tools, not Signals REST API requests. Your MCP client wraps them intools/call. Example IDs and response excerpts are illustrative; substitute your selected account’s actual values.
1. Confirm the account and read its images
Callget_account_state to inspect the workspace’s Signals-bound Meta account. Confirm it is also eligible for Actions in this workspace. For the creative calls below, supply account_id when multiple eligible active accounts exist; use that same intended account throughout. Confirm the returned workspace and Meta ad account, then check authorization.permissions for creative.read, creative.write, and actions.propose. Stop if the account or permissions do not match the intended task; issue the appropriate workspace token before proceeding.
For this example, 91 is the internal Plainrouter account ID verified in the first read, not the Meta external account ID. Keep the same account_id across the workflow. Call get-creative-library with:
asset_id from the returned assets. The human-selected source ad is a separate numeric Meta ad ID; an image hash, ad-set ID, or preview URL is not a source ad ID.
If pagination.images.has_more is true, repeat the image request with the returned pagination.images.after value as cursor. Preserve the cursor unchanged. An empty page does not prove the account has no assets of another type. If you need to add an image, complete image upload and its verification before returning here.
2. Submit one proposal for the selected pair
Callduplicate-ad-with-creative with the source ad selected by the person and the chosen asset. This example uses the illustrative image above:
status argument: Plainrouter fixes params.status to paused. It re-reads the selected source and asset under the approved account before producing the proposal. Do not ask the agent to choose a different account, guess a target, or activate the copy when validation fails.
3. Read the proposal before requesting approval in Ask
A passing proposal in Ask can return this excerpt. Other fields, including scope, evidence, and the queue URL, are omitted here:actions[].target_entity.id still identifies the source ad.
Check these fields in the complete response:
If the client reports a protocol error or a tool result with
isError: true, do not interpret transport success as proposal creation. Read the error and inspect the queue before retrying an uncertain result. The MCP error model distinguishes protocol failures from tool execution failures.
4. Follow the human decision and final outcome
For the Ask example, open the returnedinbox_url for Inbox. The older approval_queue_url field remains an alias to the same link. Review the proposal and its execution_mode_snapshot before using the generic Approve button. The decision applies to the containing batch, not just the selected action.
For the Ask example above, Approve queues execution after fresh policy checks; it does not complete the walkthrough. Follow the receipt until the copy is verified. A historical suggest-only approval appears separately under Approval recorded, nothing sent and never creates a copy. Changing current policy does not rewrite that historical snapshot.
For executed copies, verify both
status=PAUSED and effective_status=PAUSED on the exact receipt-addressed ad. A verified paused copy is not an active campaign, a delivery result, or evidence of improved advertising performance. See Paused-copy invariant for pending verification and compensation.
Give your agent a bounded request
After selecting the actual source ad and asset, use a request like this:Creative library output
get-creative-library returns account-owned images and videos, asset metadata, pagination, associated ads, and aggregated last-30-day impressions, clicks, spend, and conversions.
When requesting asset_type: "all", pagination is returned separately for images and videos. To continue from a cursor, request either image or video.
Image upload rules
Before staging an image, check its JPEG/PNG dimensions and crop for the intended placements. Meta image specifications explains placement review. Meeting a documented specification does not prove Meta acceptance; verify the upload through its execution receipt. If the image is not already in Meta,upload-asset privately stages its bytes and creates a separate upload_asset proposal. It does not immediately produce an uploaded Meta image. Ask requires approval; Full can queue a policy-allowed upload automatically. Wait for verified provider completion, then call get-creative-library again to select the returned image:<hash>.
Do not use the staged manifest ID as the asset ID for duplication. The upload-asset convenience tool accepts:
account_idwhen needed to select the same authorized accountasset_type: "image"- A bare
.jpg,.jpeg, or.pngfilename, up to 100 characters, that matches the detected content type; no directory path - Raw base64 bytes without a data URI prefix
- A rationale of up to 1,000 characters
- A stable idempotency key of up to 64 characters
Paused-copy invariant
A duplicate must be created and verified with both configured and effective status equal toPAUSED. Creating a copy never activates it. A later governed resume action is a separate proposal that uses Ask or Full and its own policy checks.
If Meta reports IN_PROCESS, the batch moves to Executed pending verification and remains Not Landed. Plainrouter performs scheduled reads for up to 48 hours. Contradictory state, rejection, or expiry triggers verified compensation, which archives the receipt-addressed copy.