{
  "markdown": "# facebook-mcp — Facebook Pages MCP Server\n\n| [![CI](https://img.shields.io/github/actions/workflow/status/IvanBBaev/facebook-mcp/ci.yml?branch=main&style=flat-square&logo=githubactions&logoColor=white&label=CI)](https://github.com/IvanBBaev/facebook-mcp/actions/workflows/ci.yml) | [![CodeQL](https://img.shields.io/github/actions/workflow/status/IvanBBaev/facebook-mcp/codeql.yml?branch=main&style=flat-square&logo=github&label=CodeQL)](https://github.com/IvanBBaev/facebook-mcp/actions/workflows/codeql.yml) |             [![License: MIT](https://img.shields.io/github/license/IvanBBaev/facebook-mcp?style=flat-square&color=blue&label=license)](LICENSE)             |              [![node](https://img.shields.io/badge/node-%E2%89%A522-brightgreen?style=flat-square&logo=nodedotjs&logoColor=white)](package.json)              | [![MCP](https://img.shields.io/badge/MCP-server-orange?style=flat-square)](https://modelcontextprotocol.io) |\n| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------: |\n|                                                                           [![status](https://img.shields.io/badge/status-pre--1.0-yellow?style=flat-square)](#)                                                                            |              [![last commit](https://img.shields.io/github/last-commit/IvanBBaev/facebook-mcp?style=flat-square&logo=git&logoColor=white&label=last%20commit)](https://github.com/IvanBBaev/facebook-mcp/commits/main)              | [![docs](https://img.shields.io/badge/docs-github.io-1877F2?style=flat-square&logo=readthedocs&logoColor=white)](https://ivanbbaev.github.io/facebook-mcp/) | [![Sponsor](https://img.shields.io/badge/Sponsor-GitHub-ea4aaa?style=flat-square&logo=githubsponsors&logoColor=white)](https://github.com/sponsors/IvanBBaev) |                                                                                                             |\n\n📖 **[Documentation site →](https://ivanbbaev.github.io/facebook-mcp/)**\n\nA local-first TypeScript [Model Context Protocol](https://modelcontextprotocol.io)\n(MCP) server for the **Meta Graph API**, focused on **Facebook Pages** —\npublishing, reading & insights, and comment/message moderation — driven from an\nMCP client (Claude, VS Code, the Inspector…) and operated locally by a Page admin\nusing their own Meta developer app. Least-privilege tokens, plan-and-apply write\nsafety, and no telemetry.\n\n> 🚧 **Status: pre-1.0, in active development.** Published on npm as\n> [`@ivanbaev/facebook-mcp`](https://www.npmjs.com/package/@ivanbaev/facebook-mcp)\n> — and the version number is the warning.\n>\n> All seven tool packages are implemented — see the [tool table](#tools) for the\n> exact surface. **Nothing has been verified against the live Graph API yet.**\n> Every test in this repository runs against fakes and recorded fixtures behind a\n> network fence that throws on a real `fetch`, so \"the tests pass\" means \"the code\n> does what the fixtures say\", not \"Meta accepted it\". A live smoke harness\n> exists ([`scripts/smoke/`](scripts/smoke/README.md)) but has not been run\n> against a real Page as part of any released state. Treat every capability below\n> as **implemented but unproven**, expect breaking changes until 1.0, and read\n> [Known limitations](#known-limitations) before you rely on anything.\n\n**Contents:** [Features](#features) · [Requirements](#requirements) ·\n[Setup](#setup) · [Client compatibility](#client-compatibility) ·\n[Configure credentials](#configure-credentials) ·\n[Permissions](#permissions-you-need-to-grant) · [Tools](#tools) ·\n[How this compares](#how-this-compares) ·\n[Known limitations](#known-limitations) · [Not in scope](#not-in-scope) ·\n[Your responsibilities](#your-responsibilities-as-the-operator) ·\n[Roadmap](#roadmap) · [Security notes](#security-notes) ·\n[Documentation](#documentation) · [Support](#support) ·\n[Trademark](#trademark) · [License](#license)\n\n## Features\n\nImplementation status only — see the status note above for what \"implemented\"\ndoes and does not mean.\n\n| Area                   | Capability                                                                      | Status                            |\n| ---------------------- | ------------------------------------------------------------------------------- | --------------------------------- |\n| **Core & diagnostics** | Identity, Page listing, rate-limit usage, `doctor` pre-flight check             | ✅ Implemented, not live-verified |\n| **Reading**            | Page & post reads, Reels, reactions, cursor pagination                          | ✅ Implemented, not live-verified |\n| **Publishing**         | Text / link / photo / video / Reels posts, scheduling, edit & delete            | ✅ Implemented, not live-verified |\n| **Insights**           | Page & post insights, flat rows + per-metric summaries, deprecation-aware       | ✅ Implemented, not live-verified |\n| **Moderation**         | Comment reads, replies, hide/delete, private reply, block/unblock               | ✅ Implemented, not live-verified |\n| **Messaging**          | Conversation reads and replies within the 24-hour window                        | ✅ Implemented, not live-verified |\n| **Ads**                | Campaign/adset/ad reads, insights, status & budget control — **off by default** | ✅ Implemented, not live-verified |\n| **Live verification**  | Every tool exercised against a real Page and a real ad account                  | ❌ Not done — see the status note |\n| **npm / MCPB release** | `npx @ivanbaev/facebook-mcp`, attested bundle, registry listing                 | ✅ Published — 0.7.0              |\n\nThe default profile exposes a deliberately small, curated tool surface — each\ntool wraps one real capability rather than mirroring every Graph edge.\n\n- **Local-first, no telemetry.** Only three Meta hosts are ever reached\n  (`graph`, `graph-video`, `rupload`); nothing phones home.\n- **Least-privilege credentials.** Works with a never-expiring System User token\n  (Business Manager) or a long-lived Page token — no App Review required for an\n  admin operating their own assets.\n- **Safe writes.** Tiered plan-and-apply gating; irreversible and spend actions\n  require out-of-band confirmation and are never bypassed by an env flag.\n- **Secret hygiene.** Value-based redaction at a single choke-point across logs,\n  errors, tool results, and the write journal.\n- **Layered architecture.** Lint-enforced `core ← api ← mcp ← tools` layering,\n  tools-as-data with a central package registry.\n\n## Requirements\n\n- Node.js **≥ 22** (enforced by `engines` and a runtime guard in the launcher;\n  the project targets the version in `.nvmrc`).\n- A Meta (Facebook) developer app — a **Business**-type app at Standard Access is\n  enough; no App Review is needed to operate your own assets.\n- A Facebook **Page** (and, for the opt-in `ads` package, an **ad account**) you\n  administer.\n\n## Setup\n\n### (a) Via npx\n\nConfigure credentials first (see [below](#configure-credentials)), then run the\npre-flight check:\n\n```bash\nnpx -y @ivanbaev/facebook-mcp doctor   # token, scopes, package matrix\n```\n\nRegister it with your MCP client:\n\n```json\n{\n  \"mcpServers\": {\n    \"facebook\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@ivanbaev/facebook-mcp\"]\n    }\n  }\n}\n```\n\n**Claude Code plugin** (installs the server wired up):\n\n```bash\n/plugin marketplace add IvanBBaev/facebook-mcp\n/plugin install facebook-mcp\n```\n\n**Claude Desktop** takes the `.mcpb` bundle attached to the\n[latest release](https://github.com/IvanBBaev/facebook-mcp/releases/latest). It\ncarries a build-provenance attestation, so you can prove it came out of this\nrepository's workflow before you install it:\n\n```bash\ngh attestation verify facebook-mcp-0.7.0.mcpb --repo IvanBBaev/facebook-mcp\n```\n\n### (b) From source\n\nFor development, or to run a commit that is not released yet:\n\n```bash\ngit clone https://github.com/IvanBBaev/facebook-mcp.git\ncd facebook-mcp\nnpm install\nnpm run build\nnode build/index.js doctor   # pre-flight: token, scopes, package matrix\nnode build/index.js          # or: ./bin/facebook-mcp.mjs\n```\n\nPoint your MCP client at that command with an absolute path:\n\n```json\n{\n  \"mcpServers\": {\n    \"facebook\": {\n      \"command\": \"node\",\n      \"args\": [\"/absolute/path/to/facebook-mcp/build/index.js\"],\n      \"env\": { \"FB_SYSTEM_TOKEN\": \"…\", \"FB_PAGE_ID\": \"…\" }\n    }\n  }\n}\n```\n\n## Client compatibility\n\nThis is a standard stdio MCP server with no client-specific code, so it should\nwork anywhere the protocol does. **\"Should\" is the operative word:** the table\nrecords the configuration each client needs and whether that path has actually\nbeen exercised — not a promise.\n\n| Client                             | How you register it                                              | Verified?                                      |\n| ---------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------- |\n| **Claude Desktop**                 | `claude_desktop_config.json` → `mcpServers`, or a `.mcpb` bundle | ❌ Not yet — bundle never installed end-to-end |\n| **Claude Code**                    | `claude mcp add`, or the plugin marketplace in this repo         | ❌ Not yet                                     |\n| **VS Code (Copilot Chat / agent)** | `.vscode/mcp.json` → `servers`                                   | ❌ Not yet                                     |\n| **Cursor**                         | `~/.cursor/mcp.json` → `mcpServers`                              | ❌ Not yet                                     |\n| **Windsurf, Zed, Cline, …**        | any client that speaks stdio JSON-RPC                            | ❌ Not yet                                     |\n| **MCP Inspector**                  | point it at `node build/index.js`                                | ❌ Not yet                                     |\n\nWhat **is** verified, by automated test:\n\n- **stdio framing** — a test spawns the built server as a real subprocess, runs\n  the full `initialize` → `tools/list` → `tools/call` handshake over pipes, and\n  asserts that stdout carries protocol frames only (all logging goes to stderr).\n- **Tool contracts** — every tool's input/output schema, annotations, write tier\n  and error mapping are unit-tested against fakes and recorded fixtures.\n- **The HTTP transport** — loopback binding, bearer-token rejection and session\n  handling, again against a real local server.\n\nNone of that involves an MCP client or the Meta API. If you get it working with\na client, [say so in an issue](https://github.com/IvanBBaev/facebook-mcp/issues) —\nthat is how this table turns into ✅.\n\n### Platform notes\n\nCI runs the full check on Linux (Node 22/24/26) and Windows (Node 22). macOS is\nthe primary development platform but is not in CI. Paths for the env file, the\nwrite journal and `FB_MEDIA_DIR` follow XDG on POSIX and `%APPDATA%` on Windows.\n\n## Configure credentials\n\nfacebook-mcp authenticates with a token **you already control** — there is no\nApp Review, no OAuth callback server, and no hosted component. Provide **at least\none** of the token variables below; the most specific wins (`FB_SYSTEM_TOKEN` →\n`FB_ACCESS_TOKEN` → `FB_PAGE_TOKEN`):\n\n- **`FB_SYSTEM_TOKEN`** — a never-expiring **System User token** (Business\n  Manager). Recommended: it does not expire and is scoped to the assets you\n  assign it.\n- **`FB_ACCESS_TOKEN`** — a Meta user access token (a long-lived one preferred).\n- **`FB_PAGE_TOKEN`** — a long-lived **Page token**, the no-Business-Manager\n  fallback.\n\nGrant only the permissions the packages you enable actually need\n([full list below](#permissions-you-need-to-grant)), and set **`FB_APP_SECRET`**\nso `appsecret_proof` is attached to every call — that makes a stolen bare token\nunusable on its own. Settings are read from an env file at the XDG/`%APPDATA%`\nconfig path, or from real environment variables (which take precedence).\n\nIf you would rather not assemble the env file by hand, run\n`node build/index.js setup-token` — the guided flow exchanges and classifies a\ntoken and writes the env file for you (`--page=<id>`, `--env-file=<path>`,\n`--force` to overwrite, `--no-write`/`--dry-run` to rehearse; pass the token via\n`FB_SETUP_TOKEN` rather than on the command line). See\n[docs/runbooks/onboarding.md](docs/runbooks/onboarding.md) for the full walkthrough.\n\nThen run `node build/index.js doctor` before anything else: it inspects the\ntoken, reports type, expiry and granted scopes, and prints a per-package\nusable / partial / blocked matrix so you find a missing permission before a tool\ncall does.\n\n`node build/index.js --version` (or `-v`) prints the server, Node and MCP SDK\nversions on one line and exits — it needs no credential, so it still answers on\nan install that cannot start:\n\n```text\nfacebook-mcp 0.7.0 (node v22.23.0, darwin arm64, sdk 1.30.0)\n```\n\nThe bare server version is always the second field, so `--version | awk '{print\n$2}'` keeps working. The same three versions plus the pinned Graph API version\nare reported by `facebook_whoami` in its `server` object (`name`, `version`,\n`apiVersion`, `sdkVersion`). `doctor`, `setup-token` and `--version` are the only\narguments that exit on their own; **anything else starts the stdio server** and\nwaits on JSON-RPC.\n\n### Environment variables\n\nProvide at least one token; everything else is optional tuning. Variables marked\n**Secret** are never logged or returned by a tool.\n\n<!-- BEGIN GENERATED: env -->\n\n| Variable                    | Required |                 Default                  | Description                                                                                                              |\n| --------------------------- | :------: | :--------------------------------------: | ------------------------------------------------------------------------------------------------------------------------ |\n| `FB_SYSTEM_TOKEN`           | one of¹  |                    —                     | **Secret.** System User token (Business Manager). Recommended; wins over the other two.                                  |\n| `FB_ACCESS_TOKEN`           | one of¹  |                    —                     | **Secret.** Meta user access token (a long-lived one preferred).                                                         |\n| `FB_PAGE_TOKEN`             | one of¹  |                    —                     | **Secret.** Long-lived Page token — the no-Business-Manager fallback.                                                    |\n| `FB_APP_ID`                 |    no    |                    —                     | Meta app ID. With `FB_APP_SECRET` it forms the app token used to inspect tokens.                                         |\n| `FB_APP_SECRET`             |    no    |                    —                     | **Secret.** When set, `appsecret_proof` is attached so a stolen bare token is unusable.                                  |\n| `FB_PAGE_ID`                |    no    |                    —                     | Default Page ID for Page-scoped tools when a call omits `profile`.                                                       |\n| `FB_API_VERSION`            |    no    |                 `v23.0`                  | Graph API version to pin. Off-default values are accepted, but only the default is tested.                               |\n| `FB_REQUEST_TIMEOUT_MS`     |    no    |                 `60000`                  | Per-request timeout in milliseconds (1–600000).                                                                          |\n| `FB_HOST_CONCURRENCY`       |    no    |                   `4`                    | Max parallel requests per Graph host (1–64).                                                                             |\n| `FB_MAX_RESULT_CHARS`       |    no    |                 `25000`                  | Character budget before a tool result is truncated (500–10000000).                                                       |\n| `FB_WRITE_MODE`             |    no    |                  `plan`                  | `plan` (default) previews a write without mutating; `apply` executes. Never covers the irreversible/spend tiers.         |\n| `FB_CONFIRM_TOKEN`          |    no    |                    —                     | **Secret.** Out-of-band confirmation token authorizing gated write / spend actions, for clients that cannot prompt.      |\n| `FB_MEDIA_DIR`              |    no    |                    —                     | Directory permitted as a source for local media uploads. Unset ⇒ URL-only, local file access disabled.                   |\n| `FB_JOURNAL_PATH`           |    no    |        XDG / %APPDATA% state path        | Path to the append-only, rotating write journal (0600).                                                                  |\n| `FB_TOOL_PACKAGES`          |    no    | core profile (all packages except `ads`) | Comma-separated packages or profiles to enable. `core` is always forced on; `ads` is opt-in.                             |\n| `FB_PACKAGES_DENY`          |    no    |                    —                     | Packages to exclude even if enabled by `FB_TOOL_PACKAGES`.                                                               |\n| `FB_PACKAGES_READONLY`      |    no    |                    —                     | Packages whose write tools are not registered; their read tools stay.                                                    |\n| `FB_TRANSPORT`              |    no    |                 `stdio`                  | `stdio` (default) or `http` (loopback-only Streamable HTTP for local agent clients).                                     |\n| `FB_HTTP_TOKEN`             | if http  |                    —                     | **Secret.** Bearer token required by the `http` transport; it fails closed without it.                                   |\n| `FB_HTTP_PORT`              |    no    |                  `3000`                  | TCP port for the `http` transport (the bind host is fixed to loopback `127.0.0.1`).                                      |\n| `FB_AD_ACCOUNT_ID`          |    no    |                    —                     | Ad account ID for the opt-in `ads` package.                                                                              |\n| `FB_ADS_BUDGET_CEILING`     |    no    |                    —                     | Hard budget ceiling for ads writes, in minor currency units (non-negative integer).                                      |\n| `FB_LOG_LEVEL`              |    no    |                  `info`                  | Stderr log verbosity: `debug`, `info`, `warn`, `error`.                                                                  |\n| `FB_SETUP_TOKEN`            |    no    |                    —                     | **Secret.** Short-lived user token consumed once by `setup-token`; the safe alternative to passing it as a CLI argument. |\n| `FB_PROFILE_<NAME>_PAGE_ID` |    no    |                    —                     | Page ID for a named profile, e.g. FB_PROFILE_BRAND_A_PAGE_ID.                                                            |\n| `FB_PROFILE_<NAME>_TOKEN`   |    no    |                    —                     | **Secret.** Optional per-profile token override for the matching FB_PROFILE_<NAME>_PAGE_ID.                              |\n\n¹ Provide at least one of `FB_SYSTEM_TOKEN`, `FB_ACCESS_TOKEN` or `FB_PAGE_TOKEN`.\nA full, commented template lives in [`.env.example`](.env.example).\n\n<!-- END GENERATED -->\n\n## Permissions you need to grant\n\n<!-- BEGIN GENERATED: scopes -->\n\nGrant only what the packages you actually enable require. The scopes below\nare the ones this server asks for; `node build/index.js doctor` compares them\nagainst what your token really has and prints a per-package usable / partial /\nblocked matrix. `business_management` is deliberately **not** in this list — it\nis a setup-only permission that should never ride on a runtime token.\n\n| Package      | Required Graph permissions                             |\n| ------------ | ------------------------------------------------------ |\n| `core`       | `pages_show_list`<br>`pages_read_engagement`           |\n| `reader`     | `pages_read_engagement`<br>`pages_read_user_content`   |\n| `posts`      | `pages_manage_posts`<br>`pages_read_engagement`        |\n| `insights`   | `read_insights`                                        |\n| `moderation` | `pages_read_user_content`<br>`pages_manage_engagement` |\n| `messages`   | `pages_messaging`<br>`pages_manage_metadata`           |\n| `ads`        | `ads_read`<br>`ads_management`                         |\n\n<details>\n<summary>Per-tool scopes (a tool marked <em>inherited</em> has no finer mapping and falls back to its package set)</summary>\n\n| Tool                            | Required Graph permissions                                         |\n| ------------------------------- | ------------------------------------------------------------------ |\n| `facebook_whoami`               | _(none — the token itself is enough)_                              |\n| `facebook_list_pages`           | `pages_show_list`                                                  |\n| `facebook_get_page`             | `pages_read_engagement`                                            |\n| `facebook_usage`                | _(none — the token itself is enough)_                              |\n| `facebook_list_posts`           | `pages_read_engagement`                                            |\n| `facebook_get_post`             | `pages_read_engagement`                                            |\n| `facebook_list_reels`           | `pages_read_engagement`                                            |\n| `facebook_get_reactions`        | `pages_read_engagement`                                            |\n| `facebook_create_post`          | `pages_manage_posts`                                               |\n| `facebook_create_photo_post`    | `pages_manage_posts`                                               |\n| `facebook_create_video_post`    | `pages_manage_posts`                                               |\n| `facebook_create_reel`          | `pages_manage_posts`                                               |\n| `facebook_update_post`          | `pages_manage_posts`                                               |\n| `facebook_delete_post`          | `pages_manage_posts`                                               |\n| `facebook_list_scheduled_posts` | `pages_read_engagement`                                            |\n| `facebook_get_video_status`     | `pages_manage_posts`, `pages_read_engagement` _(inherited)_        |\n| `facebook_page_insights`        | `read_insights`                                                    |\n| `facebook_post_insights`        | `read_insights`                                                    |\n| `facebook_reel_insights`        | `read_insights`                                                    |\n| `facebook_list_comments`        | `pages_read_user_content`                                          |\n| `facebook_get_comment`          | `pages_read_user_content`                                          |\n| `facebook_reply_to_comment`     | `pages_manage_engagement`                                          |\n| `facebook_hide_comment`         | `pages_manage_engagement`                                          |\n| `facebook_delete_comment`       | `pages_manage_engagement`, `pages_read_user_content`               |\n| `facebook_private_reply`        | `pages_messaging`, `pages_manage_engagement`                       |\n| `facebook_block_user`           | `pages_read_user_content`, `pages_manage_engagement` _(inherited)_ |\n| `facebook_unblock_user`         | `pages_read_user_content`, `pages_manage_engagement` _(inherited)_ |\n| `facebook_list_conversations`   | `pages_messaging`, `pages_manage_metadata`                         |\n| `facebook_get_conversation`     | `pages_messaging`, `pages_manage_metadata`                         |\n| `facebook_send_message`         | `pages_messaging`                                                  |\n| `facebook_list_campaigns`       | `ads_read`                                                         |\n| `facebook_list_adsets`          | `ads_read`                                                         |\n| `facebook_list_ads`             | `ads_read`                                                         |\n| `facebook_get_ad_object`        | `ads_read`                                                         |\n| `facebook_ads_insights`         | `ads_read`                                                         |\n| `facebook_ads_report_status`    | `ads_read`                                                         |\n| `facebook_update_ad_object`     | `ads_management`                                                   |\n\n</details>\n\n<!-- END GENERATED -->\n\n## Tools\n\nPackages are the unit of exposure: you enable and disable whole packages with\n`FB_TOOL_PACKAGES`, and `FB_PACKAGES_READONLY` drops a package's write tools\nwhile keeping its reads.\n\n<!-- BEGIN GENERATED: packages -->\n\n| Package      |  On by default  | Tools            | Default write mode | What it covers                                                                                                                                                                                          |\n| ------------ | :-------------: | ---------------- | :----------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `core`       |       yes       | 4 read           |         —          | Always-on identity, Page discovery and rate-limit diagnostics (read-only).                                                                                                                              |\n| `reader`     |       yes       | 4 read           |         —          | Read-only access to a Page's own content: posts (four edges), single posts, Reels and reaction totals.                                                                                                  |\n| `posts`      |       yes       | 2 read + 6 write |       `plan`       | Publish, schedule, edit and delete Page posts, photos, videos and Reels (plan-first: every write previews before it applies).                                                                           |\n| `insights`   |       yes       | 3 read           |         —          | Page, post and Reel insights: compact reshaped metric series, aggregate totals and post-2025 metric-rename guidance (read-only).                                                                        |\n| `moderation` |       yes       | 2 read + 6 write |      `apply`       | Read and moderate comments on Page content (list, reply, hide, delete, private reply) and maintain the blocked-users list.                                                                              |\n| `messages`   |       yes       | 2 read + 1 write |       `plan`       | Messenger conversations for a Page: poll the inbox, read a thread (untrusted content wrapped, attachments as placeholders) and send one private reply inside the 24-hour window. Plan-first by default. |\n| `ads`        | **no** (opt-in) | 6 read + 1 write |       `plan`       | Marketing API access: campaign / ad-set / ad listings with delivery truth, single-object reads, insights with async report runs, and plan-gated status and budget control. Off by default.              |\n\n<!-- END GENERATED -->\n\n<!-- BEGIN GENERATED: tools -->\n\n**37 tools in 7 packages.** 6 packages are on by default; the rest are opt-in via `FB_TOOL_PACKAGES`. Tier `read` never mutates. `reversible` writes are gated by `FB_WRITE_MODE`; `irreversible` and `spend` additionally require a per-call `apply` plus the `plan_id` of a preview you just ran, and are never unlocked by an environment variable alone.\n\n| Package      | Tool                            |      Tier      | Purpose                                                                                                                                                                    |\n| ------------ | ------------------------------- | :------------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `core`       | `facebook_whoami`               |     `read`     | Report the identity behind the configured token (type, validity, granted permissions, expiry) plus the server, MCP SDK and pinned Graph API version.                       |\n| `core`       | `facebook_list_pages`           |     `read`     | List the Facebook Pages the operator administers (via /me/accounts): id, name, category, the granted tasks, and whether a Page token is available.                         |\n| `core`       | `facebook_get_page`             |     `read`     | Fetch metadata for one Page — name, category, follower/fan counts, publish state, new-Page-experience flag and video upload limits.                                        |\n| `core`       | `facebook_usage`                |     `read`     | Report the most recent Graph rate-limit signals (X-App-Usage, X-Business-Use-Case-Usage, x-fb-ads-insights-throttle) as usage percentages, so you can back off before…     |\n| `reader`     | `facebook_list_posts`           |     `read`     | List a Page's posts, one cursor page at a time.                                                                                                                            |\n| `reader`     | `facebook_get_post`             |     `read`     | Fetch ONE post by its composite id (\"{page-id}_{post-id}\" as returned by facebook_list_posts).                                                                             |\n| `reader`     | `facebook_list_reels`           |     `read`     | List a Page's Reels via the /video_reels edge — the ONLY place Reels are readable.                                                                                         |\n| `reader`     | `facebook_get_reactions`        |     `read`     | Read the reactions on one post: a `totals` map per reaction type (LIKE / LOVE / CARE / HAHA / WOW / SAD / ANGRY), the overall `total`, and the list of reacting users.     |\n| `posts`      | `facebook_create_post`          |  `reversible`  | Create a Page post: plain text, a link, a multi-link card carousel, or a multi-photo carousel.                                                                             |\n| `posts`      | `facebook_create_photo_post`    |  `reversible`  | Publish ONE photo to a Page, optionally with a caption, as a draft, or scheduled.                                                                                          |\n| `posts`      | `facebook_create_video_post`    |  `reversible`  | Upload a video to a Page.                                                                                                                                                  |\n| `posts`      | `facebook_create_reel`          |  `reversible`  | Publish a Facebook Reel through the three-phase upload (start → transfer → finish) with an explicit video_state: PUBLISHED, DRAFT or SCHEDULED.                            |\n| `posts`      | `facebook_update_post`          |  `reversible`  | Edit a Page post the app itself created, or move it through the scheduled-post lifecycle.                                                                                  |\n| `posts`      | `facebook_delete_post`          | `irreversible` | Permanently delete a Page post the app itself created — including a scheduled one, which is the only way to cancel it.                                                     |\n| `posts`      | `facebook_list_scheduled_posts` |     `read`     | List the Page posts that are queued to publish later, each with its publish time echoed in UTC and in Page-local time.                                                     |\n| `posts`      | `facebook_get_video_status`     |     `read`     | Poll where one video stands in Meta's pipeline: uploading, processing, ready or error.                                                                                     |\n| `insights`   | `facebook_page_insights`        |     `read`     | Read Graph insights for one Page in a compact flat shape: one row per metric per data point ({metric, date, value}, plus `breakdown` for by-action-type metrics) and one…  |\n| `insights`   | `facebook_post_insights`        |     `read`     | Read Graph insights for one published post (post_media_view, post_clicks, post_reactions_by_type_total, video metrics, ...) in the same compact flat shape as…             |\n| `insights`   | `facebook_reel_insights`        |     `read`     | Read Graph insights for one Reel from /{video-id}/video_insights — the edge Reel metrics actually live on, which facebook_post_insights cannot reach.                      |\n| `moderation` | `facebook_list_comments`        |     `read`     | List the comments on a post, photo, video or another comment, newest-first by default.                                                                                     |\n| `moderation` | `facebook_get_comment`          |     `read`     | Read one comment by ID, optionally with its replies, and report whether a private reply is still possible (the 7-day window).                                              |\n| `moderation` | `facebook_reply_to_comment`     |  `reversible`  | Post a PUBLIC reply under a comment — visible to everyone who can see the thread.                                                                                          |\n| `moderation` | `facebook_hide_comment`         |  `reversible`  | Hide or unhide up to 50 comments in one call (`hidden:true` hides, `hidden:false` restores).                                                                               |\n| `moderation` | `facebook_delete_comment`       | `irreversible` | PERMANENTLY delete up to 50 comments.                                                                                                                                      |\n| `moderation` | `facebook_private_reply`        | `irreversible` | Send a private message to the author of a comment.                                                                                                                         |\n| `moderation` | `facebook_block_user`           |  `reversible`  | Add up to 50 PSIDs to the Page's blocked list: they can no longer comment on the Page or message it.                                                                       |\n| `moderation` | `facebook_unblock_user`         |  `reversible`  | Remove up to 50 PSIDs from the Page's blocked list, restoring their ability to comment and message.                                                                        |\n| `messages`   | `facebook_list_conversations`   |     `read`     | List Messenger conversations for a Page (platform=messenger only — never Instagram threads): id, updated_time, unread_count, message_count and the latest-message snippet. |\n| `messages`   | `facebook_get_conversation`     |     `read`     | Read one Messenger thread newest-message-first: sender, timestamp, direction and body, plus typed placeholders for images, stickers, files and shared links (attachments…  |\n| `messages`   | `facebook_send_message`         |  `reversible`  | Send ONE plain-text PRIVATE Messenger message as the Page, as a reply inside the 24-hour standard messaging window (messaging_type=RESPONSE).                              |\n| `ads`        | `facebook_list_campaigns`       |     `read`     | List campaigns under one ad account, a cursor page at a time.                                                                                                              |\n| `ads`        | `facebook_list_adsets`          |     `read`     | List ad sets under one ad account, a cursor page at a time.                                                                                                                |\n| `ads`        | `facebook_list_ads`             |     `read`     | List individual ads under one ad account, a cursor page at a time.                                                                                                         |\n| `ads`        | `facebook_get_ad_object`        |     `read`     | Read one campaign, ad set or ad by id.                                                                                                                                     |\n| `ads`        | `facebook_ads_insights`         |     `read`     | Read performance numbers (impressions, clicks, spend, reach, cpc, ctr) for an ad account, campaign, ad set or ad.                                                          |\n| `ads`        | `facebook_ads_report_status`    |     `read`     | Probe one async insights report run and, with fetch_results:true, read its rows once it has completed.                                                                     |\n| `ads`        | `facebook_update_ad_object`     | `irreversible` | Pause or resume an ads object, or change its budget.                                                                                                                       |\n\n<!-- END GENERATED -->\n\n## How this compares\n\nPoint-in-time survey (2026-07-21); the full write-up is in\n[`docs/analysis/02-market-and-positioning.md`](docs/analysis/02-market-and-positioning.md).\n\n| Project                            | Focus                 | Language   | License  | Distribution           | Notes                                                                        |\n| ---------------------------------- | --------------------- | ---------- | -------- | ---------------------- | ---------------------------------------------------------------------------- |\n| **facebook-mcp** (this)            | Pages / organic + ads | TypeScript | MIT      | npm + MCPB bundle      | Multi-Page, plan-and-apply writes, redaction, MCP annotations & outputSchema |\n| **Meta's official hosted Ads MCP** | Ads only              | hosted     | Meta ToS | `mcp.facebook.com/ads` | Business OAuth, no developer app, ~29 tools. Free.                           |\n| **pipeboard-co/meta-ads-mcp**      | Ads                   | Python     | BUSL-1.1 | hosted-remote          | Market leader (~1.1k ★), 42 tools. Not OSI open source.                      |\n| **HagaiHen/facebook-mcp-server**   | Pages                 | Python     | MIT      | source only            | The only other notable Pages server: 27 tools, single Page, no tests.        |\n\n**If you only need ads, use Meta's official server.** It is free, needs no\ndeveloper app of your own, is maintained by the vendor, and covers more ads\nsurface than this project ever will. The `ads` package here exists for one\nreason: composing ads with Pages, moderation and messaging under a single token\nand config, with the same spend gating. That is why it is **off by default** —\nads are not the reason to install this.\n\nThe reason to install this is the Pages side: multi-Page, video and Reels upload,\nscheduled-post lifecycle, insights that tell you when a metric was renamed or\nretired, and comment/message moderation — in a typed, tested, MIT-licensed\nserver that runs entirely on your machine.\n\n## Known limitations\n\nCurrent, factual, and deliberately unflattering:\n\n- **No live Graph API verification.** Nothing here has been proven against Meta's\n  servers. Fixtures encode what the API is documented to do; reality gets a vote.\n- **Published, but brand new.** 0.7.0 is on npm with provenance, the `.mcpb`\n  bundle is attached to the release and the MCP Registry listing is active — but\n  no install path has been walked end-to-end by anyone except CI. See\n  [Client compatibility](#client-compatibility) for what that means per client.\n- **Clients that cannot prompt need an operator token.** `irreversible` and\n  `spend` writes need a per-call `apply` plus a `plan_id` _and_ an out-of-band\n  confirmation the model cannot supply itself. Where the client advertises the\n  MCP `elicitation` capability, the server asks the human operator through it;\n  where it does not, the caller must pass the `FB_CONFIRM_TOKEN` value as the\n  tool's `confirm_token` argument. With neither route, those tools return\n  `confirmation_denied`.\n- **Upload progress depends on the client asking for it.** Chunked video and\n  Reel uploads emit `notifications/progress` per chunk — but only when the caller\n  supplies a `progressToken` on the request, as the MCP spec requires. A client\n  that does not send one gets no frames, and a long upload just looks slow.\n- **Insights metrics move under you.** Meta retired and renamed a large batch of\n  Page/post metrics across three waves (2024-09, 2025-11 and 2026-06-15). The\n  insights tools classify a requested metric and tell you when one is renamed or\n  gone instead of silently returning nothing — but the underlying data loss is\n  Meta's, and no wrapper can undo it.\n- **Messaging is bound by Meta's 24-hour window.** A conversation that has gone\n  quiet for more than 24 hours cannot be replied to without a message tag, and\n  this server does not paper over that.\n- **Single maintainer, pre-1.0.** Interfaces may change without a deprecation\n  period until 1.0.\n\n## Not in scope\n\nThings people reasonably expect from a \"Facebook MCP server\" that this one does\n**not** do. Listed so you can rule it out in thirty seconds instead of after an\ninstall:\n\n- **Personal profiles and Groups.** Publishing to a personal timeline has no\n  API, and the Groups API was discontinued in April 2024. This server operates\n  **Pages** — nothing else.\n- **Instagram, Threads, WhatsApp.** Different products, different permission\n  sets. Possible sibling servers one day; not this one.\n- **Webhooks / real-time ingestion.** A local stdio server has no public URL to\n  receive callbacks on. Reads are polled, by design.\n- **Boosting an organic post** (`/{page-id}/promotions`). The organic→ads bridge\n  is the most-requested crossover feature and is deliberately parked post-1.0 —\n  it needs the ads package plus spend gating that has been thought through, not\n  bolted on.\n- **Page Stories.** The publishing endpoints exist but are unverified; Stories\n  are not promised for 1.0 and stay out until a live run proves them.\n- **Events, Live video, album/photo-library reads, Page profile editing,\n  organic post targeting.** Real endpoints, outside the post / video / Reels /\n  scheduling / moderation surface this server commits to.\n- **Multi-tenant or hosted operation, serving other businesses' ad accounts.**\n  The design targets one operator, Standard Access, own assets, own machine.\n  Anything else needs App Review and Business Verification, which is a different\n  product.\n\nThe full reasoning is in\n[`docs/analysis/01-goals-and-scope.md`](docs/analysis/01-goals-and-scope.md).\n\n## Your responsibilities as the operator\n\nThis server automates actions Meta attributes to **you**, under your app and\nyour token. Automating them does not exempt you from the rules that govern them:\n\n- **Meta's [Platform Terms](https://developers.facebook.com/terms/) and\n  [Developer Policies](https://developers.facebook.com/devpolicy/) still apply** —\n  including the anti-spam and automated-behaviour rules. Bulk or repetitive\n  posting, commenting, or messaging can get a Page restricted or an app disabled,\n  and the fact that a model chose the timing is not a defence.\n- **Messenger automation must be disclosed.** Meta expects users to know when\n  they are talking to an automated system. If you wire the messaging tools to\n  answer people, tell them.\n- **Content and consent are yours.** The tools will publish whatever you point\n  them at; deciding that you have the rights to it — and, for private replies\n  and DMs, that the contact is expected — is not something a wrapper can do.\n- **This is not legal advice.** It is the honest note that a capable automation\n  tool comes with obligations, and this project would rather say so up front.\n\nThe security-side counterpart is in\n[`SECURITY.md`](SECURITY.md#out-of-scope-for-the-threat-model).\n\n## Roadmap\n\nWork is tracked publicly on the\n[**facebook-mcp roadmap** board](https://github.com/users/IvanBBaev/projects/3)\nand grouped into release milestones:\n\n| Milestone                                                                               | Scope                                                             |\n| --------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |\n| [v0.1.0](https://github.com/IvanBBaev/facebook-mcp/milestone/1) — Core                  | Foundation + `core` tools, live smoke harness                     |\n| [v0.2.0](https://github.com/IvanBBaev/facebook-mcp/milestone/2) — Reader & publishing   | Post/Reels reads, publishing, scheduling, photo/video/Reels media |\n| [v0.3.0](https://github.com/IvanBBaev/facebook-mcp/milestone/3) — Insights & moderation | Page/post insights, comment moderation, blocking                  |\n| [v0.4.0](https://github.com/IvanBBaev/facebook-mcp/milestone/4) — Messaging             | Conversations and message sending                                 |\n| [v1.0.0](https://github.com/IvanBBaev/facebook-mcp/milestone/6) — Stable                | Live verification, metadata SSOT, release rail, npm publish       |\n| [v1.1.0](https://github.com/IvanBBaev/facebook-mcp/milestone/5) — Ads                   | Ads read + control, opt-in and off by default                     |\n\n**v1.0.0 ships without the ads package** — deliberately. The Pages surface is\nthe product; ads is opt-in, off by default, and lands in 1.1.0. The code for it\nis already in the working tree, which is exactly why the milestone is about\n_verification_, not implementation: milestones close when a surface has been\n**verified live** against Meta's servers and released, not when the code lands.\nThe binding version map is\n[`docs/analysis/10-v1-release-definition.md`](docs/analysis/10-v1-release-definition.md).\n\nThe design behind each item is written up in advance in\n[`docs/analysis/`](docs/analysis/README.md) — the roadmap is a consequence of\nthat corpus, not a replacement for it.\n\n## Security notes\n\n- **Three-host fence.** Only `graph.facebook.com`, `graph-video.facebook.com`\n  and `rupload.facebook.com` are ever contacted — the allowlist is fixed in code\n  and not user-configurable, so a redirected or mistyped host cannot silently\n  receive a token.\n- **Plan-and-apply write gating.** Writes default to `plan` (a non-mutating\n  preview); `apply` executes. The exception is `moderation`, which defaults to\n  `apply` because hiding a comment is high-volume, reversible work — and\n  `FB_WRITE_MODE` overrides any package default outright, in either direction, so\n  the mode is an operator decision rather than a per-tool promise. What the mode\n  cannot touch: irreversible and spend actions always require an out-of-band\n  confirmation, and anything that reaches a live audience (publishing a post or a\n  Reel, publishing a scheduled post early, sending a DM) additionally requires a\n  `plan_id` bound to a preview of that exact call. No env flag bypasses either.\n- **Single-choke-point redaction.** Secret values are stripped at one place\n  before anything reaches logs, errors, tool results or the write journal; Page\n  access tokens are derived to a boolean and their values never enter a payload.\n- **No telemetry, local-first.** The server logs only to `stderr`, collects\n  nothing, and phones home nowhere. The `http` transport binds loopback\n  (`127.0.0.1`) only and fails closed without `FB_HTTP_TOKEN`.\n\nSee [SECURITY.md](SECURITY.md) for the full model and vulnerability reporting.\n\n## Documentation\n\n- **Design corpus** — the full pre-implementation analysis lives in\n  [`docs/analysis/`](docs/analysis/README.md): goals & scope, market positioning,\n  Graph API landscape, auth & security model, architecture, tool catalog, risks,\n  roadmap, corner cases, the v1.0 release definition, and the parallel\n  task-breakdown that drives development.\n- **Runbooks** — operational procedures in [`docs/runbooks/`](docs/runbooks/).\n- **Documentation site** — [ivanbbaev.github.io/facebook-mcp](https://ivanbbaev.github.io/facebook-mcp/).\n\nThe environment table, the package/tool tables and the permission tables above\nare generated from the code by `npm run metadata`; CI fails if they drift.\n\n## Support\n\nBest-effort, single-maintainer support runs through GitHub — see\n[SUPPORT.md](SUPPORT.md) for how to file bugs, feature requests and security\nreports.\n\nThis project is built and maintained in my own time. If it helps, a tip keeps it\ngoing:\n\n- **[GitHub Sponsors](https://github.com/sponsors/IvanBBaev)** — one-off or\n  recurring, no platform fee.\n- **[Ko-fi](https://ko-fi.com/ivanbbaev)** — quick one-off support (also accepts\n  PayPal), the fallback for anyone without a GitHub account.\n- **[Donatree](https://donatr.ee/ivanbbaev/)** — every donation method on one\n  page, including local payment options.\n\n[![Sponsor on GitHub](https://img.shields.io/badge/Sponsor-GitHub-ea4aaa?style=flat-square&logo=githubsponsors&logoColor=white)](https://github.com/sponsors/IvanBBaev)\n[![Support on Ko-fi](https://img.shields.io/badge/Ko--fi-Support-ff5e5b?style=flat-square&logo=kofi&logoColor=white)](https://ko-fi.com/ivanbbaev)\n[![Donate via Donatree](https://img.shields.io/badge/Donatree-Donate-34d399?style=flat-square&logo=liberapay&logoColor=white)](https://donatr.ee/ivanbbaev/)\n\nDonating buys no priority support and no SLA — see [SUPPORT.md](SUPPORT.md). If\nmoney is not an option, starring the repository or filing a good bug report\nhelps just as much.\n\n## Trademark\n\nThis is an independent, community-built project and is not affiliated with,\nendorsed by, or sponsored by Meta Platforms, Inc. Facebook, Meta and related\nmarks are trademarks of Meta Platforms, Inc., used here only nominatively to\nindicate compatibility.\n\n## License\n\n[MIT](LICENSE) © 2026 Ivan Baev\n",
  "bytes": 51099,
  "sha": "117a6ede1d05b49d215552cfb34c80e9b644be68b126dea3a33d23e34fcbf43f",
  "repo_slug": "ivanbbaev/facebook-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_ivanbbaev_facebook_mcp_e858422e/readme"
}