{"name":"io.github.IvanBBaev/facebook-mcp","slug":"ivanbbaev-facebook-mcp","title":null,"description":"Facebook Pages MCP server for the Meta Graph API — publishing, insights, moderation, messaging","url":"https://mcp.market/server/ivanbbaev-facebook-mcp","rating":null,"grade":"B","score":83,"certified":false,"status":"active","category":"other","tags":[],"presence":{"score":35,"stars":2,"forks":2,"downloads_week":326,"last_push_at":"2026-10-29T19:24:45.000Z","license":"MIT"},"uptime":null,"claimed":false,"transport":"npm","callable_via_gateway":false,"default_price_micros":0,"repository":"https://github.com/IvanBBaev/facebook-mcp","website":"https://ivanbbaev.github.io/facebook-mcp/","version":"0.8.0","remotes":[],"packages":[{"registryType":"npm","identifier":"@ivanbaev/facebook-mcp","version":"0.8.0","transport":{"type":"stdio"},"environmentVariables":[{"description":"System-user access token (Business Manager). Takes precedence over FB_ACCESS_TOKEN and FB_PAGE_TOKEN when several are set.","format":"string","isSecret":true,"name":"FB_SYSTEM_TOKEN"},{"description":"Primary user access token. At least one of FB_SYSTEM_TOKEN, FB_ACCESS_TOKEN or FB_PAGE_TOKEN must be set.","format":"string","isSecret":true,"name":"FB_ACCESS_TOKEN"},{"description":"Long-lived Page access token used as a fallback credential when no user or system-user token is configured. It belongs to exactly one Page, so set FB_PAGE_ID to that Page ID alongside it (the doctor / facebook_whoami reports it as the acting Page); a Page token without its Page ID is bound to nothing.","format":"string","isSecret":true,"name":"FB_PAGE_TOKEN"},{"description":"Meta app ID; combined with FB_APP_SECRET it forms the app access token used to authorize /debug_token inspection.","format":"string","name":"FB_APP_ID"},{"description":"Meta app secret. When set, appsecret_proof is attached to every call so a stolen bare token cannot be used on its own.","format":"string","isSecret":true,"name":"FB_APP_SECRET"},{"description":"Default Facebook Page ID, used when a tool call omits an explicit profile argument. Required when FB_PAGE_TOKEN is the only credential: it names the Page that token belongs to.","format":"string","name":"FB_PAGE_ID"},{"description":"Graph API version to target. Defaults to the tested pinned version; other values are accepted verbatim as an escape hatch but are not tested.","format":"string","default":"v26.0","name":"FB_API_VERSION"},{"description":"Marketing API version the ads tools target (ad accounts, campaigns, ad sets, ads, insights, async reports). The Marketing API retires versions on its own, shorter schedule, so it is pinned separately from FB_API_VERSION. Other values are accepted verbatim as an escape hatch but are not tested.","format":"string","default":"v26.0","name":"FB_ADS_API_VERSION"},{"description":"Per-request timeout in milliseconds; integer in [1, 600000].","format":"number","default":"60000","name":"FB_REQUEST_TIMEOUT_MS"},{"description":"Maximum number of in-flight requests per Graph host; integer in [1, 64].","format":"number","default":"4","name":"FB_HOST_CONCURRENCY"},{"description":"Character budget applied by the result shaper before a tool result is truncated; integer in [500, 10000000].","format":"number","default":"25000","name":"FB_MAX_RESULT_CHARS"},{"description":"Write gating mode: plan (validating dry-run preview, the default) or apply. It never covers the irreversible and spend tiers, which always need a per-call apply plus a plan_id.","format":"string","default":"plan","choices":["plan","apply"],"name":"FB_WRITE_MODE"},{"description":"Operator confirmation token for out-of-band approval of irreversible or spend actions. The server prompts through MCP elicitation where the client supports it; otherwise the caller passes this value as the confirm_token tool argument. At least 16 characters — a shorter value fails startup; mint one with openssl rand -hex 32.","format":"string","isSecret":true,"name":"FB_CONFIRM_TOKEN"},{"description":"Directory permitted for local media uploads. Unset means URL-only uploads and no local file access at all.","format":"filepath","name":"FB_MEDIA_DIR"},{"description":"Path to the append-only write journal. Defaults to the XDG/%APPDATA% state path; the file is created owner-only (0600) and rotates by size.","format":"filepath","name":"FB_JOURNAL_PATH"},{"description":"Path to the small JSON file where facebook_get_activity_since keeps, per Page, the horizon of the last complete read. Defaults to the XDG/%APPDATA% state path next to the journal; the file holds Page ids and timestamps only and is written atomically, owner-only (0600).","format":"filepath","name":"FB_ACTIVITY_STATE_PATH"},{"description":"Directory where the insights tools write a CSV or JSON file when called with `output`. Defaults to `exports/` under the XDG/%APPDATA% state path. Files are written atomically and owner-only (0600) and are never overwritten; a name collision gets a numeric suffix.","format":"filepath","name":"FB_EXPORT_DIR"},{"description":"Comma-separated tool packages or profiles to expose (e.g. core,posts,reader, or the profiles core|all|reader|publisher|moderator|ads). Omit for the default profile, which excludes ads.","format":"string","name":"FB_TOOL_PACKAGES"},{"description":"Comma-separated packages OR profiles to exclude even when FB_TOOL_PACKAGES enables them; deny wins over allow. Profile names expand here exactly as they do in FB_TOOL_PACKAGES, and a profile beats a same-spelled package, so FB_PACKAGES_DENY=core denies the whole six-package core profile rather than the single core package. The core package is then forced back on regardless, because its identity and diagnostic tools are what you need to debug the surface you just narrowed. An unrecognized name is a startup error, not a silently ignored token.","format":"string","name":"FB_PACKAGES_DENY"},{"description":"Comma-separated packages OR profiles whose write tools are not registered at all; the read tools of those packages stay available. Profile names expand as they do in FB_TOOL_PACKAGES, so FB_PACKAGES_READONLY=core makes every default package read-only in one token. An unrecognized name is a startup error.","format":"string","name":"FB_PACKAGES_READONLY"},{"description":"Transport protocol: stdio (default) or http. The http transport binds 127.0.0.1 only and fails closed without FB_HTTP_TOKEN.","format":"string","default":"stdio","choices":["stdio","http"],"name":"FB_TRANSPORT"},{"description":"Bearer token guarding the HTTP transport; required when FB_TRANSPORT=http (the server refuses to start without it). At least 16 characters — a shorter value is refused (under stdio it is dropped with a warning); mint one with openssl rand -hex 32.","format":"string","isSecret":true,"name":"FB_HTTP_TOKEN"},{"description":"Port for the HTTP transport (loopback only); used when FB_TRANSPORT=http. Integer in [1, 65535].","format":"number","default":"3000","name":"FB_HTTP_PORT"},{"description":"Default ad account ID (act_… or the bare numeric id) for the opt-in ads package.","format":"string","name":"FB_AD_ACCOUNT_ID"},{"description":"Hard ceiling for any ads budget write, in minor units of the ad account's own currency (e.g. cents for USD). Non-negative integer; a write above it is refused. No currency conversion: size it for the account's currency (1000 is $10 but only 1000 JPY).","format":"number","name":"FB_ADS_BUDGET_CEILING"},{"description":"Largest campaign spend_cap (the lifetime total a campaign may spend) that an ads write may set, in minor units of the ad account's own currency. Non-negative integer; a cap above it is refused, never clamped. Unset: every write that sets a campaign spend cap is refused. No currency conversion, same as FB_ADS_BUDGET_CEILING.","format":"number","name":"FB_ADS_CAMPAIGN_SPEND_CAP_MAX"},{"description":"Stderr log verbosity: debug, info, warn or error. Logs never go to stdout — that is the stdio protocol channel.","format":"string","default":"info","choices":["debug","info","warn","error"],"name":"FB_LOG_LEVEL"}]}],"tools":[{"name":"facebook_ads_insights","description":"Read performance numbers (impressions, clicks, spend, reach, cpc, ctr) for","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_ads_report_status","description":"Probe one async insights report run and, with fetch_results:true, read its","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_comment_on_post","description":"Post a PUBLIC top-level comment as the Page on a post — e.g. a first comment","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_create_photo_post","description":"Publish ONE photo to a Page, optionally with a caption, as a draft, or","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_create_post","description":"Create a Page post: plain text, a link, a multi-link card carousel, or a","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_create_reel","description":"Publish a Facebook Reel through the three-phase upload (start → transfer","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_create_story","description":"Publish a photo or video story on the Page. A story is public at once for","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_create_video_post","description":"Upload a video to a Page. A local path inside FB_MEDIA_DIR is streamed","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_delete_comment","description":"PERMANENTLY delete up to 50 comments. This cannot be undone — prefer","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_delete_post","description":"Permanently delete a Page post the app itself created — including a","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_duplicate_ad_object","description":"Copy one campaign, ad set or ad into a new PAUSED copy (an ad set copy stays in its campaign,","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_edit_comment","description":"Replace the text of a comment the Page itself wrote — e.g. fix a typo in a","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_get_activity_since","description":"What is new on a Page since a point in time, in one call: new comments","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_get_ad_object","description":"Read one campaign, ad set or ad by id. Pass `level` when you know it — the","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_get_ad_preview","description":"Show how an existing ad, an existing ad creative, or a Page post used as an","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_get_ad_set_targeting","description":"Read one ad set's audience and summarise it in plain terms: countries, counts of regions / cities / locales, age range, genders, placements, and flags for detailed targeting, custom audiences, exclusions and Advantage+ audience. `editable_by_this_server` says whether facebook_update_ad_set_targeting can change it, and `not_editable_because` says why not. Pass include_raw:true to also get the raw t","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_get_comment","description":"Read one comment by ID, optionally with its replies, and report whether a","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_get_page","description":"Fetch metadata for one Page — name, category, follower/fan counts, publish","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_get_page_report","description":"One-call Page performance report over a window (default last 28 days,","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_get_post","description":"Fetch ONE post by its composite id (\"{page-id}_{post-id}\" as returned by","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_get_posts_insights","description":"Lifetime insights for several posts in one call, as a compact table: one","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_get_reactions","description":"Read the reactions on one post: a `totals` map per reaction type","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_get_video_status","description":"Poll where one video stands in Meta's pipeline: uploading, processing,","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_hide_comment","description":"Hide or unhide up to 50 comments in one call (`hidden:true` hides,","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_like_comment","description":"Like up to 50 comments as the Page, or unlike them with `unlike:true`.","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_list_ads","description":"List individual ads under one ad account, a cursor page at a time. This is","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_list_adsets","description":"List ad sets under one ad account, a cursor page at a time. Ad sets are","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_list_albums","description":"List a Page's photo albums, one cursor page at a time: `id`, `name`,","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_list_campaigns","description":"List campaigns under one ad account, a cursor page at a time. Each record","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_list_comments","description":"List the comments on a post, photo, video or another comment, newest-first","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_list_pages","description":"List the Facebook Pages the operator administers (via /me/accounts): id,","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_list_photos","description":"List photos, one cursor page at a time: an album's photos when `album_id`","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_list_posts","description":"List a Page's posts, one cursor page at a time. `edge` selects WHICH posts:","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_list_reels","description":"List a Page's Reels via the /video_reels edge — the ONLY place Reels are","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_list_scheduled_posts","description":"List the Page posts that are queued to publish later, each with its publish","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_list_stories","description":"List a Page's Stories via the /stories edge, one cursor page at a time:","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_page_insights","description":"Read Graph insights for one Page in a compact flat shape: one row per","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_post_insights","description":"Read Graph insights for one published post (post_media_view, post_clicks,","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_private_reply","description":"Send a private message to the author of a comment, or of a visitor post on","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_reel_insights","description":"Read Graph insights for one Reel from /{video-id}/video_insights — the","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_reply_and_hide_comment","description":"Post a PUBLIC reply under a comment and then hide that comment, in one","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_reply_to_comment","description":"Post a PUBLIC reply under a comment — visible to everyone who can see the","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_triage_comments","description":"A moderation queue in one call: the comments on the Page's most recent","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_update_ad_object","description":"Pause or resume an ads object, change its budget, or set a campaign spend cap. Plan-first: without","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_update_ad_set_targeting","description":"Change only the countries and/or the age range of one ad set's audience; everything else in its targeting is kept exactly as it is. Refused when the audience is more complex than that (custom audiences, detailed targeting, regions/cities/zips, exclusions, Advantage+ audience on) — check editable_by_this_server with facebook_get_ad_set_targeting first. Adding EU countries to an audience that had no","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_update_post","description":"Edit a Page post the app itself created, or move it through the scheduled-post","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_upload_ad_image","description":"Upload one local image (JPEG, PNG, GIF, BMP, TIFF or WEBP, at most 30 MB, inside FB_MEDIA_DIR) to the ad account's image library and return its hash, which creatives reference it by. Creates no ad and changes no delivery. Plan-first: without apply:true this returns a preview (file, size, account) and uploads NOTHING; applying requires apply:true plus the plan_id from that preview. Uploads are dedu","write_action":true,"price_micros":0,"input_schema":null},{"name":"facebook_usage","description":"Report the most recent Graph rate-limit signals (X-App-Usage,","write_action":false,"price_micros":0,"input_schema":null},{"name":"facebook_whoami","description":"Report the identity behind the configured token (type, validity, granted","write_action":false,"price_micros":0,"input_schema":null}],"scan":{"score":83,"grade":"B","scanned_at":"2026-10-30T18:17:48.079Z","report":{"scannerVersion":"0.1.10","scannedAt":"2026-10-30T18:17:48.036Z","components":{"code":{"score":25,"max":25,"notes":["154 source files scanned"]},"reliability":{"score":-1,"max":20,"notes":["no gateway calls yet and no remote to probe"]},"poisoning":{"score":-1,"max":15,"notes":["tools not inspected (local package is not executed); not counted"]},"auth":{"score":6,"max":15,"notes":["static API keys via environment variables"]},"maintenance":{"score":15,"max":15,"notes":["last push 1 days ago"]},"identity":{"score":8,"max":10,"notes":["registry namespace matches repository owner","GitHub account older than a year"]}},"findings":[],"inputs":{"packages":[{"registryType":"npm","identifier":"@ivanbaev/facebook-mcp","version":"0.8.0","found":true,"license":"MIT","hasInstallScripts":false,"dependencyCount":3,"publishedAt":"2026-10-28T19:25:04.630Z","repositoryUrl":"git+https://github.com/IvanBBaev/facebook-mcp.git","weeklyDownloads":326}],"repo":{"found":true,"owner":"IvanBBaev","repo":"facebook-mcp","archived":false,"pushedAt":"2026-10-29T19:24:45Z","stars":2,"forks":2,"openIssues":9,"ownerType":"User","ownerAvatarUrl":"https://avatars.githubusercontent.com/u/126177?v=4","ownerCreatedAt":"2009-09-12T18:55:01Z","license":"MIT"},"icon":{"url":"https://avatars.githubusercontent.com/u/126177?v=4&s=128","source":"registry","width":128,"height":128},"presence":{"stars":2,"forks":2,"downloadsWeek":326,"license":"MIT","lastPushAt":"2026-10-29T19:24:45.000Z","score":35}}}},"grade_history":[],"reviews":[]}