Ask what your Meta ads spend and what to stop; pause and change budgets inside limits you set.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Turns a standing order the person describes into an autopilot rule, checked every hour. It is saved in DRY RUN: it records what it would do but changes nothing until the person switches it to live on the Autopilot screen. The result shows what it would match right now; tell them. level: campaign, adset or ad. window_days: 1 (today), 3, 7, 14 or 30, always including today. conditions (all must hold, 1 to 4): metric is one of spend, impressions, link_clicks, link_ctr (percent), cpc, cpm, frequency, landing_page_views, purchases, cpa, roas, results and cost_per_result (results by each campaign's own goal); op is gt, gte, lt, lte or eq; money values in the account currency's major units (200 means R200.00). A cost metric never matches something with no results, so 'spent R200 and no purchases' is spend gte 200 plus purchases eq 0. A rule judging a cost or a rate must also have a floor (spend, impressions or link clicks at least something), or it is refused. action: pause, alert (no change), lower_budget or raise_budget with percent 5 to 50 (budget rules only at campaign or adset level; raises only where the person allowed autopilot to raise in Settings). cooldown_hours (default 24) is how often it may act on the same thing. Ask the person for any number they did not give.
For lower_budget and raise_budget.
Only things whose name contains this text.
This tool isn't marked read-only, so it may change something on the server or in an account you connected.
Pick your client. Values in capitals, like YOUR_TOKEN, are yours to fill in.
Run in a terminal
claude mcp add --transport http ads https://fama.best/api/mcp
Turns a standing order the person describes into an autopilot rule, checked every hour. It is saved in DRY RUN: it records what it would do but changes nothing until the person switches it to live on the Autopilot screen. The result shows what it would match right now; tell them. level: campaign, adset or ad. window_days: 1 (today), 3, 7, 14 or 30, always including today. conditions (all must hold, 1 to 4): metric is one of spend, impressions, link_clicks, link_ctr (percent), cpc, cpm, frequency, landing_page_views, purchases, cpa, roas, results and cost_per_result (results by each campaign's own goal); op is gt, gte, lt, lte or eq; money values in the account currency's major units (200 means R200.00). A cost metric never matches something with no results, so 'spent R200 and no purchases' is spend gte 200 plus purchases eq 0. A rule judging a cost or a rate must also have a floor (spend, impressions or link clicks at least something), or it is refused. action: pause, alert (no change), lower_budget or raise_budget with percent 5 to 50 (budget rules only at campaign or adset level; raises only where the person allowed autopilot to raise in Settings). cooldown_hours (default 24) is how often it may act on the same thing. Ask the person for any number they did not give.
| Argument | Type | Description |
|---|---|---|
| name* | string | |
| level* | string | |
| action* | string | |
| percent | integer | For lower_budget and raise_budget. |
| conditions* | array | |
| window_days* | any | |
| name_contains | string | Only things whose name contains this text. |
| cooldown_hours | integer |
{
"type": "object",
"required": [
"name",
"level",
"window_days",
"conditions",
"action"
],
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 3
},
"level": {
"enum": [
"campaign",
"adset",
"ad"
],
"type": "string"
},
"action": {
"enum": [
"pause",
"alert",
"lower_budget",
"raise_budget"
],
"type": "string"
},
"percent": {
"type": "integer",
"maximum": 50,
"minimum": 5,
"description": "For lower_budget and raise_budget."
},
"conditions": {
"type": "array",
"items": {
"type": "object",
"required": [
"metric",
"op",
"value"
],
"properties": {
"op": {
"enum": [
"gt",
"gte",
"lt",
"lte",
"eq"
],
"type": "string"
},
"value": {
"type": "number",
"minimum": 0
},
"metric": {
"enum": [
"spend",
"impressions",
"link_clicks",
"link_ctr",
"cpc",
"cpm",
"frequency",
"landing_page_views",
"purchases",
"cpa",
"roas",
"results",
"cost_per_result"
],
"type": "string"
}
},
"additionalProperties": false
},
"maxItems": 4,
"minItems": 1
},
"window_days": {
"anyOf": [
{
"type": "number",
"const": 1
},
{
"type": "number",
"const": 3
},
{
"type": "number",
"const": 7
},
{
"type": "number",
"const": 14
},
{
"type": "number",
"const": 30
}
]
},
"name_contains": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "Only things whose name contains this text."
},
"cooldown_hours": {
"type": "integer",
"maximum": 168,
"minimum": 6
}
},
"additionalProperties": false
}Copies an ad set with its ads, always created PAUSED, optionally renamed and, for ABO ad sets, with its own daily budget. The usual way to scale a winner without resetting its learning. The copy spends nothing until it is switched on (switch_on). Meta copies an ad set with its ads in one step only when it has 3 ads or fewer; for a bigger one, say so and point the person to Duplicate in Ads Manager. Inside the limits the person set, it happens at once and the result says what Meta now reports. Over a soft limit it waits for the person to confirm; past a hard limit (the account's daily cap, read-only mode) it is refused. Read `result` before saying what happened.
| Argument | Type | Description |
|---|---|---|
| reason* | string | Why, with the numbers that justify it. Recorded in the activity log. |
| adset_id* | string | |
| new_name | string | |
| daily_budget | number | ABO only. Major units. |
{
"type": "object",
"required": [
"adset_id",
"reason"
],
"properties": {
"reason": {
"type": "string",
"maxLength": 1200,
"minLength": 10,
"description": "Why, with the numbers that justify it. Recorded in the activity log."
},
"adset_id": {
"type": "string"
},
"new_name": {
"type": "string",
"maxLength": 200,
"minLength": 3
},
"daily_budget": {
"type": "number",
"description": "ABO only. Major units.",
"exclusiveMinimum": 0
}
},
"additionalProperties": false
}Call this FIRST for any question about the account's state, spend or a drop in results. Returns the ad account's billing status, today's spend against what its live budgets should have spent by this hour, yesterday's spend, and every ad set's delivery over the last 48 hours, including ad sets that read ACTIVE but have stopped delivering and the cause when one can be named (a disapproved ad, an unsettled balance). A campaign reading ACTIVE in Ads Manager does not mean it is spending; this tool is how you tell.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}Performance for a window, at account, campaign, adset or ad level, optionally by day or broken down by age, gender, placement or platform. Every ratio (CTR, CPC, CPM, CPA, ROAS, frequency, hook rate) is computed from raw counts. Windows ending yesterday (last_7d, last_14d, last_30d) exclude today, as Meta's do. Purchases count one action type, never several summed. Rows with no impressions are omitted. Use since/until (YYYY-MM-DD, account timezone) for a custom window instead of date_preset.
| Argument | Type | Description |
|---|---|---|
| level* | string | |
| since | string | |
| until | string | |
| breakdown | string | |
| entity_ids | array | Restrict to these ids at the chosen level. |
| date_preset | string | |
| time_increment | string | 'day' returns one row per entity per day. Default 'all'. |
{
"type": "object",
"required": [
"level"
],
"properties": {
"level": {
"enum": [
"account",
"campaign",
"adset",
"ad"
],
"type": "string"
},
"since": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"until": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"breakdown": {
"enum": [
"age",
"gender",
"placement",
"platform"
],
"type": "string"
},
"entity_ids": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 20,
"description": "Restrict to these ids at the chosen level."
},
"date_preset": {
"enum": [
"today",
"yesterday",
"last_7d",
"last_14d",
"last_30d"
],
"type": "string"
},
"time_increment": {
"enum": [
"all",
"day"
],
"type": "string",
"description": "'day' returns one row per entity per day. Default 'all'."
}
},
"additionalProperties": false
}Returns every campaign, its ad sets and its ads with ids, configured and effective status, objective, budget (and whether it lives on the campaign as CBO or on the ad set as ABO), optimisation goal, audience temperature, targeting summary, learning stage, and each ad's format, headline, primary text and hook. Use it to find entity ids before drafting a change and to check where a budget lives.
| Argument | Type | Description |
|---|---|---|
| include_paused | boolean | Include paused campaigns. Default true. |
{
"type": "object",
"properties": {
"include_paused": {
"type": "boolean",
"description": "Include paused campaigns. Default true."
}
},
"additionalProperties": false
}One change by id: whether it was made, is waiting, was refused or failed, what it changed, the limits it met, and what Meta reported afterwards. Call it after the person says they confirmed something, before saying it is live.
| Argument | Type | Description |
|---|---|---|
| change_id* | string |
{
"type": "object",
"required": [
"change_id"
],
"properties": {
"change_id": {
"type": "string",
"maxLength": 64,
"minLength": 1
}
},
"additionalProperties": false
}Compares every delivering ad's last 7 complete days with the 7 before: seven-day frequency against the limit (3 for cold traffic, 6 for retargeting), link CTR change and CPA change week over week, and a verdict: fatigued (frequency over the limit and CTR or CPA worsening), watch, healthy, or too_little_data. Call it before recommending new creative or moving budget between ads.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}The answer to the four questions people ask most, for a period against the period before it: where the money is going (spend by campaign and ad set, with shares), what is working (winners: cheaper results than the account on enough spend to trust), which creatives are winning (ads ranked by cost per result, with link CTR and hook rate), and what needs stopping or fixing (spend with no results, results at twice the account's cost, live ad sets that spent nothing, rejected ads, tired creative), each with the sentence and numbers behind it and what pausing it saves a day. Each campaign is judged by its own goal: sales by purchases, traffic by landing page views; leads, awareness and engagement campaigns are never called waste for having no purchases. Call it for 'how are my ads doing', 'what should I stop', 'what is working', 'which creative is best', or before recommending where budget should go. Periods end yesterday except today.
| Argument | Type | Description |
|---|---|---|
| since | string | For custom: first day, account timezone. |
| until | string | For custom: last day. |
| period | string | Default last_7d. |
{
"type": "object",
"properties": {
"since": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "For custom: first day, account timezone."
},
"until": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "For custom: last day."
},
"period": {
"enum": [
"today",
"yesterday",
"last_7d",
"last_14d",
"last_30d",
"custom"
],
"type": "string",
"description": "Default last_7d."
}
},
"additionalProperties": false
}The account's pixels or datasets: when each last fired, daily counts per event (PageView, ViewContent, AddToCart, InitiateCheckout, Purchase), whether events carry a value, whether any arrive server-side through the Conversions API, and the problems that break optimisation.
| Argument | Type | Description |
|---|---|---|
| days | integer | Days of history. Default 7. |
{
"type": "object",
"properties": {
"days": {
"type": "integer",
"maximum": 30,
"minimum": 1,
"description": "Days of history. Default 7."
}
},
"additionalProperties": false
}The account's autopilot rules: standing orders checked every hour (for example, pause any ad set that spent R200 with no purchases in 3 days). Each with its plain-words description, its mode (dry_run records what it would do, live acts, off does nothing) and when it was last checked.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}Lists changes for this ad account, newest first: by default the ones waiting for the person to confirm (over a limit, or from a key that may only propose), with a link where they confirm each. 'done' lists what was made, refused or failed, and by whom (the chat, an AI tool, autopilot, a person).
| Argument | Type | Description |
|---|---|---|
| status | string | waiting (default), done, or all. |
{
"type": "object",
"properties": {
"status": {
"enum": [
"waiting",
"done",
"all"
],
"type": "string",
"description": "waiting (default), done, or all."
}
},
"additionalProperties": false
}Pauses a campaign, ad set or ad in Meta. Pausing only stops spend, so it is always inside the limits and happens at once (unless the account is set to confirm every change, or read-only mode is on). Pausing the only active ad in an ad set stops the whole ad set; the result says so. Use it when the person asks, or when they agreed to your recommendation. Inside the limits the person set, it happens at once and the result says what Meta now reports. Over a soft limit it waits for the person to confirm; past a hard limit (the account's daily cap, read-only mode) it is refused. Read `result` before saying what happened.
| Argument | Type | Description |
|---|---|---|
| reason* | string | Why, with the numbers that justify it. Recorded in the activity log. |
| entity_id* | string |
{
"type": "object",
"required": [
"entity_id",
"reason"
],
"properties": {
"reason": {
"type": "string",
"maxLength": 1200,
"minLength": 10,
"description": "Why, with the numbers that justify it. Recorded in the activity log."
},
"entity_id": {
"type": "string"
}
},
"additionalProperties": false
}Sets a new daily budget on a CBO campaign or an ABO ad set (use the entity that actually holds the budget). Lowering is inside the limits and happens at once. A raise over the person's single-raise limit (25% by default) or over the per-campaign limit waits for them to confirm; a raise that takes the account over its daily cap is refused. A change over 20% can restart Meta's learning phase. Inside the limits the person set, it happens at once and the result says what Meta now reports. Over a soft limit it waits for the person to confirm; past a hard limit (the account's daily cap, read-only mode) it is refused. Read `result` before saying what happened.
| Argument | Type | Description |
|---|---|---|
| reason* | string | Why, with the numbers that justify it. Recorded in the activity log. |
| entity_id* | string | Campaign id (CBO) or ad set id (ABO). |
| new_daily_budget* | number | New daily budget in the account currency's major units, e.g. 360 for R360.00. |
{
"type": "object",
"required": [
"entity_id",
"new_daily_budget",
"reason"
],
"properties": {
"reason": {
"type": "string",
"maxLength": 1200,
"minLength": 10,
"description": "Why, with the numbers that justify it. Recorded in the activity log."
},
"entity_id": {
"type": "string",
"description": "Campaign id (CBO) or ad set id (ABO)."
},
"new_daily_budget": {
"type": "number",
"description": "New daily budget in the account currency's major units, e.g. 360 for R360.00.",
"exclusiveMinimum": 0
}
},
"additionalProperties": false
}Switches ON a paused campaign, ad set or ad, so it can spend. Use it only when the person asks for it or clearly agrees. The account's daily cap is a hard limit: a switch-on that would take live daily budgets over it is refused. Something switched on under a paused campaign or ad set will not spend until that is on too; the result says so. Inside the limits the person set, it happens at once and the result says what Meta now reports. Over a soft limit it waits for the person to confirm; past a hard limit (the account's daily cap, read-only mode) it is refused. Read `result` before saying what happened.
| Argument | Type | Description |
|---|---|---|
| reason* | string | Why, with the numbers that justify it. Recorded in the activity log. |
| entity_id* | string |
{
"type": "object",
"required": [
"entity_id",
"reason"
],
"properties": {
"reason": {
"type": "string",
"maxLength": 1200,
"minLength": 10,
"description": "Why, with the numbers that justify it. Recorded in the activity log."
},
"entity_id": {
"type": "string"
}
},
"additionalProperties": false
}We read every tool's name, description and inputs the way the model will, looking for instructions hidden from you. A clean result means no warning signs, not a guarantee. Scanned Nov 13, 2026.