The whole thing is 4 moves:
Log in with the same profile that admins your BM. First time here? It asks you to register as a developer: confirm your email, done. No review, no waiting.
When it asks for a Business Portfolio, select YOUR Business Manager. This ties the app to your BM, which is what lets the System User use it later.
Scroll the product list until you see Marketing API, hit Set up. You do NOT need to complete any "quickstart" it offers. The product just needs to be attached to the app.
๐ก "But doesn't my app need App Review?" No. App Review is for apps that other people log into. Your app only talks to YOUR OWN Business Manager through a System User, and for that, Dev Mode + standard access is enough. This is the part 99% of tutorials get wrong.
A System User is a robot employee inside your Business Manager. It has no password, no login, no 2FA, no "we noticed a new device" emails. It exists only to hold permissions and generate tokens. This is what your connection will run as.
Name it something obvious like "claude-media-buyer". Role: Admin. (Admin role on the system user is what allows full campaign management later. You can tighten it once everything works.)
This connects the robot to the app you created in Step 1.
Select every ad account you want Claude to control. Do the same under Pages for any page you run ads from (needed to create ads later). Client accounts shared with your BM show up here too.
๐ก The agency superpower: this step IS your client onboarding from now on. Sign a new client, get their ad account shared with your BM, assign it to this System User. Thirty seconds, zero new auth, and Claude sees the new account immediately.
Pick your app, set expiration to Never, and check exactly these three permissions:
ads_management: create, edit, pause campaignsads_read: read performance databusiness_management: see the accounts inside your BMMeta shows the token one single time. Copy it into your password manager right now, labeled "Meta System User token". If you lose it, you just generate a new one, but save yourself the trip.
โ ๏ธ This token IS the keys to your ad accounts. Anyone holding it can spend your clients' money. Never paste it in Discord, never screenshot it, never commit it to a repo. Password manager or nothing. If it ever leaks: Business Settings โ System users โ your robot โ revoke the token, generate a new one.
Open Claude Code in your agency folder, replace PASTE_YOUR_TOKEN_HERE with the token from Step 3, and paste this:
set up my meta ads mcp connection using my system user token. 1. if the old oauth server is still registered, remove it first: claude mcp remove meta-ads -s local (ignore errors if it doesn't exist) 2. check if `uvx` is installed (run: uvx --version). if it's missing, install uv first: curl -LsSf https://astral.sh/uv/install.sh | sh then restart the shell so uvx is on the PATH. 3. register the mcp server with my token, user scope so it works in every project: claude mcp add --scope user meta-ads --env META_ACCESS_TOKEN=PASTE_YOUR_TOKEN_HERE -- uvx meta-ads-mcp 4. run `claude mcp list` and confirm meta-ads shows as connected. 5. then prove it works: list my ad accounts with names, IDs and currency in a table. do not print my token back to me in any output.
Found 3 ad accounts: Account ID Name Currency act_88472910045296XX Joe's HVAC USD act_55128990371644XX Smile Dental USD act_10228005507357XX My Agency Main USD
That table means the whole chain works: app, system user, token, MCP. There is nothing else to configure, ever. This connection survives restarts, new sessions, new projects, and Meta's login moods.
โ ๏ธ Spend safety, non-negotiable: whenever you ask Claude for anything that creates or changes campaigns, end the request with "create everything PAUSED and show me before activating". The token can move real money. Claude is your media buyer, you are still the director.
Show me the last 7 days of performance for every active campaign in ad account [PASTE ACCOUNT ID]. Sort by ROAS descending. Flag any campaign with CPA above $50 or ROAS below 1.5.
Look at ad account [PASTE ACCOUNT ID]. Find the top 3 ad creatives from the last 30 days based on ROAS. Tell me what they have in common (format, hook style, CTA) and suggest 5 new creative angles based on what's working.
Create a new campaign in ad account [PASTE ACCOUNT ID] for client [CLIENT NAME]. Objective: leads. Daily budget: $50. Use the existing Page [PAGE ID] and pixel [PIXEL ID]. Create everything PAUSED and show me the full structure before I activate anything.
The token got pasted wrong (missing characters, extra space) or was revoked. Fix: generate a fresh token (Step 3), then re-run the Step 4 paste with the new one. The claude mcp add command overwrites the old registration.
The System User cannot see that asset. This is ALWAYS an assignment problem, never a token problem. Go to Business Settings โ System users โ your robot โ Assign assets, and confirm the ad account (and its Page) are assigned with Manage access. Changes apply instantly, no new token needed.
The shell has not reloaded its PATH. Close the terminal completely (or VS Code entirely, Cmd+Q / close window) and reopen it. Then re-run the Step 4 paste. On Windows, use the PowerShell installer from the uv install page.
Dev mode is fine for this setup: a System User of the SAME Business the app belongs to has full access to that Business's own assets. If you see this error, the app was created outside your BM. Check App dashboard โ Settings โ Basic โ Business verification section, and make sure the app belongs to your Business Portfolio.
Paste this in Claude Code:
run `claude mcp list` and show me the status of meta-ads. if it shows as failed, remove it and re-add it with my token using: claude mcp remove meta-ads -s user, then the claude mcp add command from before. then list my ad accounts.
It still exists (claude mcp add --transport http meta-ads "https://mcp.facebook.com/ads"), and if it works on your account, fine. But its login flow has been failing for a lot of students, and some tools are gated by Meta's gradual rollout. The System User path in this lesson has neither problem, which is why it is now the recommended route and the one our own agency runs.
Your connection is live. Before you create a single campaign with it, install this. It is the naming system our own agency runs, packaged as a Claude Code skill: the name of every campaign, ad set, and ad is the primary key of your attribution. It flows through UTMs into your CRM and reports. A space, an emoji, or a "- Copy" in a name becomes garbage in every report downstream, forever.
โฌ Download ad-naming-skill.zip
Then in your terminal:
$ mkdir -p ~/.claude/skills && unzip ~/Downloads/ad-naming-skill.zip -d ~/.claude/skills
Restart Claude Code. From now on, whenever you ask it to create or upload anything on Meta, it names everything by the system, checks the lint, sets the UTMs, and creates it all PAUSED. First run, it interviews you once for your client's product codes and builds a registry file that remembers every hook number and angle you ever use.
๐ก Why this makes the MCP stronger: the MCP gives Claude hands. This skill gives it discipline. Six months from now, when you ask "compare every LEAKY_ROOF_CHECK ad we ever ran", the answer exists because every name was a database key from day one.
Claude Code is now wired to Meta the way production systems are: your own app, a machine user, a token that never expires. Every other lesson in Module 5 runs on this connection. And your client onboarding just became "assign the ad account to the robot".
Next up: Lesson 5.4, The AI Media Buying Agent.