
Your agent needs to work inside your customers' Meta ad accounts. It pulls spend and CTR, pauses the ad set that is burning budget, and pushes a refreshed customer list into a custom audience. Meta now ships a hosted Model Context Protocol (MCP) server for ads next to the Marketing API. Both reach the same ad accounts. They differ on tool coverage, token model, and who carries the guardrails when an agent can spend money. For a multi-tenant agent, one of those differences decides the architecture. Here is the decision framework.
Both sit on the same ad account graph. What differs is the shape of the surface and who maintains it.
The ads MCP server is a Meta-hosted remote MCP server, part of Meta's ads AI connectors alongside the Ads CLI. Meta announced it in open beta on April 29, 2026. A July 16, 2026 update added two things agent builders care about: you can connect your own AI application through your own Meta developer app, and admins with full control of a business portfolio can set ads MCP server rules that limit what agents may do, from budget changes to catalog edits.
Write tools create campaigns, ad sets, and ads paused. Spending starts only through a separate ads_activate_entity call. Meta's official reference is the Ads MCP Server section of the Ads AI Connectors documentation on Meta for Developers.
What most teams call the Meta Ads API is the Marketing API, built on the Graph API and currently at v25.0. It covers campaigns, ad sets, ads, creatives, synchronous and asynchronous Insights, custom audiences, catalogs, lead ads, the Conversions API, the Ad Rules Engine, and Ads Webhooks.
Every call carries an access token: a user access token from Facebook Login, or a system user token for server-to-server work. New apps start on the Limited access tier. Full access runs through App Review and requires at least 500 Marketing API calls in the last 15 days with an error rate under 15%. The official reference is the Marketing API section of Meta's Ads and Commerce documentation.
Four dimensions decide the build: capability coverage, auth model, operational surface area, and fit per use case.
Meta's MCP inventory is broad on structure, reporting, and catalogs. The gaps sit where revenue agents work hardest.
An agent that syncs lead form submissions into a CRM cannot run on MCP; there is no lead retrieval tool. Neither can one that forwards server-side purchase events, since the signals tools read dataset stats and Event Match Quality but do not send events. Large historical pulls, such as reach breakdowns over long date ranges, need the async report-run workflow. Reacting to a disapproval or creative fatigue as it happens needs Ads Webhooks.
None of these are edge cases. They are the core of lead-gen, e-commerce, and agency automation.
MCP ships guardrails you would otherwise build: paused-by-default writes, an explicit activation step, and portfolio-level rules owned by the customer's admin. It also ships packaged analysis the raw API leaves to you, including ads_get_opportunity_score, ads_insights_anomaly_signal, ads_insights_industry_benchmark, and ads_get_errors for delivery-blocking issues.
ads_get_field_context returns field types and enum values before the model builds a query, which cuts malformed calls. Meta maintains every schema, so you write no tool definitions.
The token models differ more than the capability table suggests.
Meta documents two methods. With OAuth, the MCP client redirects the user to the Facebook Login for Business dialog, where they sign in with a Facebook account or a Meta Managed Account and approve permissions. For programmatic setups, you pass a user access token in the Authorization: Bearer header. That token needs ads_mcp_management, ads_read, ads_management, catalog_management, business_management, pages_show_list, and instagram_basic.
Individual advertisers can connect supported AI clients without owning a Meta app. For your own agent product, the redirect URL lives in your developer app's Facebook Login for Business settings. MCP does not remove your Meta app from the picture; it moves it.
The Marketing API uses the same Facebook Login Authorization Code flow. Short-lived user tokens expire in one to two hours. Your server exchanges them through the fb_exchange_token grant for a long-lived token, which Meta says generally lasts about 60 days. An expired token cannot be exchanged; the user signs in again. Password changes and permission revocation invalidate tokens early.
System user tokens do not expire and suit server-to-server work with no user present. If your app manages other people's ad accounts, Meta requires advanced access to ads_read or ads_management through App Review.
Headless MCP works with a bearer user token, but it is still a user token with a roughly 60-day life and no refresh token. System users avoid expiry, yet when client ad accounts are shared into your Business Manager, one non-expiring credential becomes the blast radius for every client.
Both paths require per-user credential isolation in a multi-tenant B2B agent. MCP's OAuth flow gives you a token per user. Direct API calls give you a credential per user. In neither case does the path itself solve storage, rotation, or revocation; those are infrastructure problems regardless of which path you choose.
Recommended reading: How to Handle Token Refresh for AI Agents
Hosting is the smallest line on the operational bill.
Meta runs the server, maintains tool schemas, and enforces paused-by-default writes and portfolio rules. You still own token custody per user, expiry and revocation detection, the re-consent flow, and tenant isolation inside your own system.
You also absorb schema drift. Hosted tools change on Meta's schedule, and the server is still in open beta. An agent prompt tuned against one tool shape can break without a deploy on your side.
You own everything the MCP path leaves to you, plus request construction, pagination cursors, async report polling, and handling Meta's numeric error codes and subcodes. You pin a Graph API version and migrate on Meta's deprecation schedule. You read throttle state from the X-Ad-Account-Usage, X-Business-Use-Case, and X-FB-Ads-Insights-Throttle headers.
You also build the guardrail MCP gives you for free: nothing stops a create call from setting status to ACTIVE.
Marketing API calls are scored per ad account: a read costs 1 point and a write costs 3. On the Limited tier the ceiling is 60 points, with a 300-second block when you hit it; Full access raises it to 9,000 with a 60-second block. Mutations cap at 100 requests per second per app and ad account. Each ad set's budget can change only 4 times per hour, and account spend caps 10 times per day.
A budget-pacing agent that nudges spend every ten minutes hits the ad set wall in its first hour. Meta's MCP docs publish no separate quota table, so design for the same account-level limits.
Both lists are specific to Meta Ads workloads, not generic MCP advice.
Picture 40 media buyers across 12 client businesses. That is 40 Meta user tokens, each with a roughly 60-day life, each revocable by its owner at any time, each invalidated by a password change. There is no refresh token to retry with. When one dies, the only recovery is getting that user back through Facebook Login, and your agent has to notice before the Monday report ships blank.
The token type is identical across paths. So is the management burden. Understanding secure token management for AI agents at scale is essential before committing to either path in production.
Scalekit's Meta Ads connector runs the Facebook Login flow through your Meta app, stores each user's credential in an AES-256 encrypted token vault, and keeps it out of the agent runtime and the model's context. Each connected account carries a status, so the agent checks for ACTIVE and sends a re-authorization link instead of failing mid-run.
One precision point: Scalekit's catalog lists one Meta Ads connector, built on the Marketing API. It does not proxy Meta's hosted MCP server. You reach its 148 tools as direct tool calls or as an MCP endpoint through a Scalekit Virtual MCP server, so the MCP vs API decision doesn't change your auth infrastructure.
Recommended reading: Token Vault: Why It's Critical for AI Agent Workflows
The build below is a read-only weekly performance agent. It runs first as direct tool calls in Python with the Claude SDK, then as a Virtual MCP server consumed by a Mastra agent in TypeScript.
The connection name is metaads, and auth is OAuth 2.0. The tools cover the MCP gaps named above.
Full schemas live in the Meta Ads connector docs.
Connection setup happens once per environment, not once per user.
The connection_name in your code must match the connection name in the dashboard exactly. This is the single most common integration error.
Each user signs in to Meta once. The agent confirms the connected account is ACTIVE before every run; in production, send the link through your UI or email instead of input().
The agent does not load the connector catalog. list_scoped_tools returns the tools the current user's connected account is authorized to call, filtered here to six read-only reporting tools. Handing the model all 148 is an accuracy problem and a cost problem: at Scalekit's rough figure of 200 tokens per tool, that is nearly 30,000 tokens before the agent does any work. The fix is not better prompting. It is surface reduction.
execute_tool runs each call under the resolved user identity. Scalekit attaches the user's Meta token server-side, so the loop never touches a credential. Tool errors, such as a Meta throttling response, go back to the model as is_error results instead of crashing the run.
A Virtual MCP server is defined once per agent role and serves every user. This role combines read-only Meta Ads reporting with Gmail send, so the digest agent reaches two connectors through one endpoint. Save config_id and mcp_server_url; every session reuses them.
Before each run, the backend confirms every connection is active for this user, then mints a short-lived session token. The default lifetime is about an hour; there is no refresh endpoint, so you call create_session_token again when you need a new one.
The Node SDK does not mint session tokens yet, so the Python backend above mints them and hands the URL and token to the Mastra app. Mastra discovers tools and schemas from the server and prefixes each with the server key, so metaads_account_insights_get reaches the model as scalekit_metaads_account_insights_get. Never share a session token across users; any request carrying it runs as that user. Set OPENAI_API_KEY alongside the two Scalekit values.
Full walkthroughs: Set up and connect a Virtual MCP server, Mastra example, and Anthropic example.
Two capabilities matter most once the agent spends real money across real tenants.
Scalekit logs every tool call with full attribution: who authorized it, which agent ran it, and the response. Logs export to your SIEM, with failures separated by source, and each execute_tool response carries an execution_id you can store next to your own run records. Meta's activity log tells you which Meta identity changed a budget. It cannot tell you which of your agents, or which run, issued that change. When a customer's security team asks why an ad set paused at 3am, the answer has to span both layers.
Recommended reading: Audit Trails for Agent Auth in B2B SaaS
Meta's ads MCP server rules govern what any agent may do on a customer's portfolio, set by that customer's admin. A Scalekit Virtual MCP server governs what one agent role in your product may see, across Meta Ads and every other connector it needs. The two stack.
One server definition serves all users. Each run gets a session token scoped to one user, and the agent sees only the tools you allowed. The endpoint is static; the identity is per user. There is no MCP server to deploy, host, or maintain.
If your agent needs a Marketing API edge the prebuilt tools do not cover, custom tools proxy the call through the same connected account. Auth, token custody, and logging stay unchanged, so the edge you add inherits the same per-user attribution as the 148 prebuilt tools. This is the same pattern used for tool calling auth patterns across any connector.
If your agent is an interactive assistant for media buyers who are present to sign in, who ask about spend, delivery errors, and catalog health, and who approve each activation, Meta's Ads MCP server is the fast path. Its paused-by-default writes are a feature there.
If your agent runs headless, syncs leads, forwards conversions, reacts to webhooks, or pulls large async reports across many client accounts, build against the Marketing API. Most production Meta Ads agents need both modes. Either way, every user brings a token with a 60-day life and no refresh token. That credential problem is identical on both paths, and it is what needs production-grade infrastructure.
For teams moving from single-tenant prototypes to multi-tenant production, the auth architecture shift is significant. How tool calling auth changes when you move from single-tenant to multi-tenant covers that transition in detail.
Building a Meta Ads agent that runs across many tenants? Talk to the Scalekit team for immediate help with connection setup, tool scoping, and Virtual MCP design. Start with the Meta Ads connector docs, browse the Scalekit connector catalog and all AgentKit connectors, or review Scalekit pricing.