get_ad_accounts
List accessible Meta ad accounts for the connected workspace.
Run Meta ad accounts, campaigns, ad sets, creatives, audiences and reporting from an assistant — deployed to your own Cloudflare account, against your own Meta app.
LABSCO SUMMARY
The design decision that shapes everything here is that the server refuses to guess who is calling: no JWT, no workspace, no Meta token binding. That is more setup than a single-user server — you supply the auth issuer — but it is the reason one deployment can serve several workspaces without their ad accounts leaking into each other. The /app page exists so you do not have to hand-sign a token just to connect the first account.
A Cloudflare Worker that speaks MCP over Streamable HTTP and calls the Meta Graph API directly, with browser-facing Meta OAuth routes alongside it. It is multi-tenant by design: Meta connections are stored per workspace in D1, access tokens are encrypted at rest, and every MCP request must carry a JWT your own application issued. The README says the server registers 39 tools; one of them, get_ad_accounts, is named in its docs.
get_ad_accountsGET /oauth/meta/start and GET /oauth/meta/callback bind the resulting Meta token to the workspace named in the caller's JWT, so the start link is never a generic public URLmeta_connections, meta_ad_accounts_cache) with short-lived OAuth state in KV/app that takes a password, runs the OAuth flow without you minting a bearer JWT by hand, and shows whether a Meta account is connectedfetch calls rather than the Meta SDK, with META_GRAPH_VERSION defaulting to v25.0Your own Cloudflare Worker deployment, your own Meta developer app with the Marketing API product added, and your own JWT issuer — the repository ships no hosted control plane, no shared Meta app and no auth provider. Required bindings are a D1 database as META_DB and a KV namespace as META_OAUTH_STATE; required secrets are JWT_SECRET or JWT_JWKS_URL, META_APP_ID, META_APP_SECRET, META_TOKEN_ENCRYPTION_KEY, and APP_UI_PASSWORD for the admin page. Every MCP request needs a bearer JWT carrying sub (or userId) and workspaceId. Default OAuth scopes are ads_management,business_management. The Meta app's callback URL must match https://<your-worker-host>/oauth/meta/callback exactly.
Build from source — git clone https://github.com/brijr/meta-mcp.git
USE CASES
Issue a JWT for that workspace, send the user through the OAuth start route, and the resulting token is bound to the workspace and encrypted before storage.
Use the reporting and insights tools against a connected account instead of exporting from Ads Manager.
Drive the campaign, ad set and creative tool families from the assistant, with the batch helpers for changes that span many objects.
One Worker, one Meta app, a JWT per workspace — connections and cached ad accounts stay separated in D1.
Listed in project code.
get_ad_accountsList accessible Meta ad accounts for the connected workspace.
get_custom_conversionsList custom conversions for an ad account or a specific pixel.
get_pagesList Facebook Pages that can be used with the connected Meta identity.
get_pixelsList Meta Pixels available on an ad account.
validate_accountRun a pre-flight validation check for an ad account.
create_ad_setCreate a Meta ad set under a campaign.
delete_ad_setDelete a Meta ad set.
duplicate_ad_setClone an existing ad set with optional overrides.
get_ad_setGet a Meta ad set by ID.
list_ad_setsList ad sets under a campaign.
update_ad_setUpdate a Meta ad set.
create_custom_audienceCreate a Meta custom audience.
create_lookalike_audienceCreate a Meta lookalike audience.
get_audience_sizeEstimate audience size for a Meta targeting specification.
get_targeting_optionsSearch Meta targeting options such as interests and demographics.
list_audiencesList custom and saved Meta audiences.
bulk_create_adsCreate multiple Meta ads in a single tool call.
bulk_update_statusUpdate status for many Meta objects at once.
clone_campaign_structureDeep-clone a campaign with its ad sets and ads.
create_campaignCreate a Meta campaign on an ad account.
delete_campaignDelete or archive a Meta campaign.
get_campaignGet campaign details by campaign ID.
list_campaignsList campaigns on an ad account.
update_campaignUpdate a Meta campaign.
create_adCreate a Meta ad under an ad set.
create_ad_creativeCreate a Meta ad creative.
get_adGet a Meta ad by ID.
get_ad_previewGenerate ad previews for a creative and placement format.
get_video_statusGet processing status for a Meta video asset.
list_adsList ads under an ad set or campaign.
update_adUpdate a Meta ad.
upload_imageUpload an image to a Meta ad account.
upload_videoUpload a video asset to a Meta ad account.
compare_adsCompare metrics across multiple Meta ads.
get_ad_metricsGet key metrics for a Meta ad.
get_adset_metricsGet key metrics for a Meta ad set.
get_campaign_metricsGet key metrics for a Meta campaign.
get_conversion_dataGet conversion-focused insight rows for a Meta object.
get_insightsPull Meta performance insights for a campaign, ad set, or ad.
BEFORE YOU INSTALL
39 tools registered in the project's code.
INSTALLATION
This one is built from source rather than installed with a single command.
Clone the repository and install dependencies (Node.js 20+ and pnpm):
git clone https://github.com/brijr/meta-mcp.git
cd meta-mcp
pnpm installwrangler.jsonc ships with the author's own Cloudflare account_id, a custom-domain route for meta-mcp.gestalt.xyz, and the IDs of the author's KV namespace and D1 database. Remove account_id and the routes entry (or set your own domain), create your own KV namespace and D1 database, and put the IDs these commands print into the META_OAUTH_STATE and META_DB bindings in wrangler.jsonc (database_name must match the D1 database you create).
pnpm wrangler kv namespace create META_OAUTH_STATE
pnpm wrangler d1 create meta-mcp-dbSet the required Worker secrets. JWT_SECRET is the secret your own app signs its JWTs with (or set JWT_JWKS_URL instead); META_APP_ID and META_APP_SECRET come from your Meta developer app; META_TOKEN_ENCRYPTION_KEY is any long random string; APP_UI_PASSWORD protects the admin page at /app.
pnpm wrangler secret put JWT_SECRET
pnpm wrangler secret put META_APP_ID
pnpm wrangler secret put META_APP_SECRET
pnpm wrangler secret put META_TOKEN_ENCRYPTION_KEY
pnpm wrangler secret put APP_UI_PASSWORDApply the D1 schema:
pnpm wrangler d1 execute META_DB --remote --file schema.sql -yDeploy the Worker with the project's deploy script (pnpm run deploy builds with xmcp and runs wrangler deploy; plain pnpm deploy is a different, built-in pnpm command):
pnpm run deployNote the public Worker URL and set META_REDIRECT_URI to https://<YOUR_WORKER_HOST>/oauth/meta/callback. In your Meta app, add the Marketing API product and a Website platform whose URL is your Worker origin, set App Domains to your Worker domain, and add the same callback URL.
Connect a Meta ad account: open https://<YOUR_WORKER_HOST>/app, enter APP_UI_PASSWORD and start the Meta sign-in there.
Connect your MCP client to https://<YOUR_WORKER_HOST>/mcp over Streamable HTTP, sending a bearer JWT issued by your app (claims sub or userId, and workspaceId) in the Authorization header. The OAuth connection and the MCP calls must use the same workspaceId.