Under one of the big "Claude runs my Facebook ads" videos, the most-liked question is short: how do I manage multiple Meta ad accounts with Claude? The answer it got was practical — one Claude project per client, so the context does not bleed. That solves the memory problem. It does not touch the access problem, and the access problem is the one that costs money.
One Claude project per client solves the memory problem, not the access problem. What decides which accounts Claude can reach is the token it acts as — so give it a dedicated business user, or a System User, scoped to only what that client owns, and let Meta enforce the boundary instead of the prompt.
Which user is Claude?
Whatever connects Claude to Meta — the official Ads MCP, a custom MCP server, a script — every call reaches Meta as one user, with that user's permissions. If that user is you, an admin of the Business Manager, then Claude can read and write every ad account you can, for every client, in every session. Nothing in the chat window narrows that. The project-per-client setup keeps the conversations apart; the token underneath them is the same and sees everything.
So the real question for an agency is not how to organise chats. It is: what is the smallest user Claude can be, per client?
The login path: a dedicated business user
Meta's own MCP connector does not take a pasted token. It sends you through Facebook Login for Business and asks for the ads permissions of whoever logs in. That is the lever: do not log in as yourself. In Business Settings, add a business user with the Employee role, assign it only the ad accounts for that client, and log the connector in as that user. Claude now physically cannot reach the accounts it was not given.
One dedicated user per client is more setup. It is also the only version where a wrong "pause the underperformers" cannot land in the wrong client's account, because the wrong account is not in the list.
The token path: a System User
If you run your own MCP server or scripts, the right identity is a System User — Meta's name for a user that represents software rather than a person. The whole setup is four calls on the Business Management API:
- Create it: POST /<BUSINESS_ID>/system_users with name and role=EMPLOYEE. Use EMPLOYEE. ADMIN is for the thing that creates other system users, not for the thing that edits campaigns.
- Install your app on it: POST /<SYSTEM_USER_ID>/applications with business_app=<APP_ID>.
- Give it exactly the accounts and exactly the tasks: POST /act_<AD_ACCOUNT_ID>/assigned_users with user=<SYSTEM_USER_ID> and tasks. The task list for an ad account is MANAGE, ADVERTISE, ANALYZE, DRAFT, AA_ANALYZE. A read-only analyst gets ANALYZE. A user that may edit ads gets ADVERTISE and ANALYZE. Nothing that runs unattended needs MANAGE — that is billing and permissions.
- Mint the token: POST /<SYSTEM_USER_ID>/access_tokens with business_app, scope and set_token_expires_in_60_days=true. By default system user tokens do not expire; the 60-day flag is the difference between a leaked token that dies on its own and one that does not. Revoking is DELETE /<SYSTEM_USER_ID>/access_tokens — you cannot delete the system user, you can kill all of its tokens.
The pattern that falls out of this: one system user per client, or one system user with a different task set per account. Either way the permission lives in Meta, not in a prompt that says "only touch account B".
Three things multi-account changes in practice
- Every call names the account. The Marketing API addresses everything as act_<ID>. When a model has ten accounts in reach, the failure mode is not malice, it is picking the wrong ID for a client with a similar name. Task scoping is what makes that mistake fail loudly instead of succeeding quietly.
- Rate limits are per ad account, not per token. On Standard Access an ad account gets roughly 300 calls plus 40 per active ad per hour. Running six clients through one token does not pool six budgets; it means the busiest account throttles first, and a throttled call is a delayed change, not a refused one. Meta's Business Use Case rate-limit header tells you where each account stands.
- Insights across accounts are separate reports. There is no cross-account read; a "portfolio" view is you (or your tool) joining six account reports. If the join is done in a chat, it is done again next time, by hand.
What none of this solves
Permissions decide what Claude may touch. They do not decide when. A session ends and the account is back to whatever Meta's own automation does; the 3am budget spike on client four is still nobody's, and a system user token with the right tasks does not wake anyone up. The two problems are separate: identity is the setup, supervision is the daily job.
If you keep one thing: the token is the operator. Give Claude a user that can only reach what that client owns, with only the tasks that client's work needs, and let Meta enforce it.
Where we sit
Everix connects one Meta ad account per workspace, through Facebook Login for Business, so the account boundary is drawn by Meta before anything runs. Inside that boundary it reads and acts on its own schedule: budget cuts and pauses execute automatically; anything that moves money up stops at a human. That is the split we think a multi-account setup needs anyway — narrow identity, automatic downside, approved upside.
If you are running several accounts through Claude today, the change worth making this week is not a better prompt. It is a smaller user.