Skip to content

Meta Pages MCP Server

A 45-tool MCP server for the Facebook, Instagram and ad accounts of my own brands, with a scope lock enforced in code and an audit log of every write.

Problem

I wanted a coding agent to manage posts, comments and ad campaigns for my own brands through the Meta Graph API, without a way for it to touch a Page or an ad account that is not mine.

Constraints

  • A mistake by the agent must not be able to reach another account or spend money by surprise
  • Meta throttles calls, and a throttled call must not look like a permission error
  • Every write needs a record of what was done and by whom

Overview

This is a stdio MCP server that I use from Claude Code. It wraps the Meta Graph API for the Facebook Page, Instagram account and ad account of my own brands. A dashboard that shares the same core code exists too, and I leave it out here. I set the design and the rules and I review the code. Coding agents wrote most of it. The repository is private, so there is no link.

It registers 45 tools: reading page details, posts, comments and insights, publishing or scheduling posts and reels on Facebook and Instagram, replying to and hiding comments, and managing ads from campaign summaries to creating campaigns, ad sets and ads and setting status or budgets.

Decisions that carry the design

One module talks to Meta, and it enforces scope. Every call goes through a single core module. Before it acts on an ID it checks that the ID belongs to the allowed brand: the Page ID, the Instagram account, the ad account, and objects that must be proven to sit inside them, such as a post, a video, a comment or an ad object. An ID that fails the check raises a scope error. This is code, not a line in a prompt, so it does not depend on the agent behaving well.

Brands are an argument, not a global. Every tool takes an optional brand and runs under it. The scope lock is then evaluated for that brand’s IDs only.

Money fails safe. The tools that create ad campaigns, ad sets and ads create them paused, and their descriptions say that nothing spends until it is activated with a separate status call. Starting spend is a deliberate second step.

Tools say what they do to the world. Read tools carry the read-only annotation, and the three tools that delete or replace a post, or delete an ad rule, carry the destructive one, so an MCP client can ask a person before running them.

Every write is recorded. Write and destructive tools are wrapped so that a successful or failed call is appended to an activity log with the tool name and its arguments. Reads are not logged.

Throttling is not forbidden. Meta’s rate-limit error codes are recognised and reported as throttling. Otherwise a throttled ownership check would read as “this object is not yours”, which is wrong and misleading to an agent that then gives up or retries blindly. Confirmed ownership is remembered, so later checks cost no API call.

What I can show

The tool count, the scope checks and the audit wrapper are all visible in the code. I do not have usage numbers, and I am not showing any account data.

Stack

  • Runtime: Node.js, ES modules
  • MCP: the official TypeScript SDK over stdio, with Zod input schemas
  • API: Meta Graph API