Skip to main content
Glama

facebook-mcp

CI

Facebook automation exposed as an MCP (Model Context Protocol) server.

Capabilities:

  • get_user_latest_post_time — a user's latest post publish time (e.g. exampleuser)

  • get_user_recent_posts — recent posts with text, time and permalink

  • search_people — keyword search for people (/search/people?q=...)

  • search_pages — keyword search for pages (/search/pages?q=...)

  • send_message — send a Messenger message

Design docs: ARCHITECTURE.en.md (English) · ARCHITECTURE.md (中文).

Status

  • M0 scaffolding — done

  • M1 transport (curl_cffi + proxy + retry/throttle) — done

  • M2 session + routes + profile client + get_user_latest_post_time — done, verified live

  • M3 search (search_people / search_pages) — done, verified live over pure HTTP

  • M4 CDP transport (cookie bootstrap + packet capture) — done

  • M5 send_message — done, verified live (browser path)

All five tools work against the live site.

Why send_message needs a browser

Messenger's web app issues the send from its service worker, and typing/sync traffic runs over a binary Lightspeed WebSocket whose frames contain no readable message body. There is no page-level GraphQL mutation to replay, and the legacy /ajax/mercury/send_messages.php endpoint is gone (404). So send_message drives the real Messenger UI through CDP (type → click send → confirm the composer clears). See ARCHITECTURE.en.md §8.3 for the evidence.

Related MCP server: Facebook MCP Server

Install

/opt/homebrew/bin/python3.11 -m venv .venv
.venv/bin/pip install -e ".[dev]"

Requires mcp>=1.2,<2 (official MCP Python SDK, mcp.server.fastmcp).

⚠️ This project intentionally pins mcp<2.

Configure

cp .env.example .env
# fill in FB_COOKIE / FB_COOKIE_FILE for authenticated operations

A proxy is often required to reach Facebook. The transport resolves it automatically: FB_PROXY → HTTPS_PROXY env → macOS system proxy.

Tools

Tool

Needs login

Description

get_user_latest_post_time

no

Latest post publish time (UTC) for a username

get_user_recent_posts

no

Recent posts (text, time, permalink)

search_people

yes

Keyword search for people

search_pages

yes

Keyword search for pages

send_message

yes (+ browser)

Send a Messenger message

Credentials: ~/.facebook-mcp/

Cookies live outside the repository, one directory per Facebook account:

~/.facebook-mcp/                      # 0700
└── accounts/
    └── default/                      # 0700
        ├── cookies.txt               # 0600, Netscape format
        └── account.json              # 0600, metadata + per-account overrides

Which tools need credentials — measured in an incognito Chrome with zero Facebook cookies (ARCHITECTURE.en.md §8.1):

Tool

Needs cookies

Evidence when logged out

get_user_latest_post_time / get_user_recent_posts

no

200 + full timeline

search_people / search_pages

yes

404 on the search page; GraphQL replies "Rate limit exceeded"

send_message

no (but needs a browser)

uses Chrome's own session

Populate an account

# A. Export from a logged-in Chrome (one time)
bash tools/launch_chrome_debug.sh
.venv/bin/python tools/export_cookies.py --account default

# B. Or decrypt straight from your Chrome profile
.venv/bin/python tools/import_cookies.py --account default

# Inspect
.venv/bin/python tools/export_cookies.py --list

Then run without a browser:

FB_TRANSPORT_MODE=http .venv/bin/facebook-mcp     # uses accounts/default

Or let the server borrow your live Chrome (cookies bootstrapped lazily):

FB_TRANSPORT_MODE=auto .venv/bin/facebook-mcp

Multiple accounts

Per process (fully isolated, recommended):

{
  "mcpServers": {
    "facebook-default": {
      "command": ".../.venv/bin/facebook-mcp",
      "env": { "FB_ACCOUNT": "default", "FB_TRANSPORT_MODE": "http" }
    },
    "facebook-work": {
      "command": ".../.venv/bin/facebook-mcp",
      "env": { "FB_ACCOUNT": "work", "FB_TRANSPORT_MODE": "http" }
    }
  }
}

Per call — every tool takes an optional account argument:

search_pages(q="pest control", account="work")
send_message(recipient="exampleuser", text="hi", account="work")

Each account can bind its own browser via cdp_url in its account.json (e.g. {"cdp_url": "http://127.0.0.1:9223"}), so two accounts never fight over the same Chrome tab.

Maintenance: Facebook ships a new frontend build

GraphQL doc_ids and variables templates change. Re-capture them:

.venv/bin/python tools/sniff.py --navigate "https://www.facebook.com/search/pages?q=pest%20control" \
                               --seconds 20 --save-templates

Helpers

Script

Purpose

tools/probe.py

Ad-hoc live check of a service

tools/sniff.py

Capture GraphQL doc_id / variables templates

tools/export_cookies.py

Export Chrome cookies into ~/.facebook-mcp/accounts/<name>/

tools/import_cookies.py

Decrypt cookies straight from the Chrome profile

tools/launch_chrome_debug.sh

Launch Chrome with DevTools + dedicated profile

tools/check_layers.py

Verify the layered import rules (CI-friendly)

Development

make install     # .venv (Python 3.11) + dev dependencies
make hooks       # commit-msg hook + commit template
make check       # everything CI runs: lint, format, layers, tests, MCP smoke

Target

What it does

make lint

ruff check src tools tests

make fmt

ruff format (rewrites)

make fmt-check

ruff format --check

make layers

verifies the layered import rules + no cycles

make test

pytest -q (146 tests, fully offline)

make smoke

MCP stdio handshake + tools/list validation

make test-commits

validate commit messages on the current branch

make chrome / make chrome-stop

per-account Chrome: make chrome ACCOUNT=work

make check

all of the above

CI (.github/workflows/ci.yml)

Job

Runs

lint & architecture

ruff lint + format, tools/check_layers.py, commit-message convention (PRs), secret-leak guard

test

pytest on Python 3.11/3.12/3.13 (Ubuntu) and 3.11 (macOS) + MCP smoke

build & install wheel

python -m build, asserts routes/templates/*.json is packaged, installs the wheel in a clean venv

Tests are fully offline — a local http.server and a mock DevTools (WebSocket) server stand in for Facebook and Chrome, so CI needs no network or credentials.

Verify against the live site

.venv/bin/python tools/probe.py profile exampleuser
.venv/bin/python tools/probe.py search pages "pest control"

Run

.venv/bin/facebook-mcp            # stdio transport (default)
# or
.venv/bin/python -m facebook_mcp

HTTP transports are available too (the SDK supports them):

# streamable-http on 127.0.0.1:8000/mcp
.venv/bin/python -c "from facebook_mcp.server import mcp; mcp.run('streamable-http')"

MCP client config (example)

{
  "mcpServers": {
    "facebook": {
      "command": "/Users/jin/Documents/GitHub/facebook-mcp/.venv/bin/facebook-mcp",
      "env": { "FB_COOKIE_FILE": "/path/to/cookies.txt" }
    }
  }
}

Commit convention

Conventional Commits, enforced locally by make hooks and in CI by tools/commit_msg.py:

feat(search): paginate results with page_info.end_cursor
fix(accounts): keep cookies out of the repository
docs: explain why send_message needs a browser

Types: feat fix docs test refactor perf build ci chore revert. Scopes: core transport session routes clients services server accounts cdp http proxy profile post search message tools tests ci docs deps release. Subject: imperative, lowercase, no trailing period, header ≤ 72 chars.

See CONTRIBUTING.md for the full rules and examples.

License

MIT © facebook-mcp contributors

Not affiliated with, endorsed by, or supported by Meta/Facebook. Use it only with accounts you own or are authorized to automate, and respect Facebook's terms of service and local anti-spam / privacy law.

All usernames, page names and ids in this repository are placeholders (exampleuser, 100000000000001, …). See CONTRIBUTING.md → Documentation privacy.

Available Tools

5 tools
get_user_latest_post_timeA

Get the publish time (UTC) of a user's latest post by username. Example username: 'exampleuser' (no URL, no leading '@'). Optional account name selecting the credential set under ~/.facebook-mcp/accounts//. Defaults to the configured account.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountNo
usernameYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesWhether the lookup succeeded
errorNoError message when ok=False
post_urlNoPermalink of the latest post
usernameYesRequested username
post_textNoSnippet of the latest post
latest_post_timeNoPublish time (UTC)

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It usefully discloses that the value is UTC, where account credentials live (~/.facebook-mcp/accounts/<account>/), and that the account defaults to the configured one, but it says nothing about auth failures, private/nonexistent users, or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three compact sentences, front-loaded with the resource and return value before the input-format and account caveats. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value details need not be repeated, and both parameters are covered. The only gap is behavior on failure cases (unknown user, private profile), which is minor for a simple read-only lookup.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the parameter meaning, and it does: it specifies the username format (no URL, no leading '@') with an example, and explains that account selects the credential set under ~/.facebook-mcp/accounts/<account>/ and defaults to the configured account.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: the publish time (UTC) of a user's latest post, keyed by username. The 'latest post' scoping implicitly distinguishes it from the sibling get_user_recent_posts.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied by the 'latest post' phrasing; there is no explicit statement of when to pick this over get_user_recent_posts or any other sibling. It does give input-format guidance (username, account), but that is parameter help rather than when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_user_recent_postsB

List a user's recent posts (newest first), including text, UTC publish time and permalink. Optional account name selecting the credential set under ~/.facebook-mcp/accounts//. Defaults to the configured account.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
accountNo
usernameYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It usefully discloses ordering (newest first) and the credential-set semantics of the account path plus its default, but says nothing about auth requirements, rate limits, or failure behavior when an account is absent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the primary action and return contents. The second sentence is long but each clause carries real information about account resolution.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be restated, and the description does cover ordering and account resolution. However, with no annotations and 0% schema coverage it leaves the limit parameter and any failure/edge behavior undocumented.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It does explain the account parameter well (credential set under ~/.facebook-mcp/accounts/<account>/, default configured account), but limit and its default of 10 go entirely unexplained in both schema and description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (List) and resource (a user's recent posts) plus ordering and the fields returned, which implicitly separates it from get_user_latest_post_time. It never names that sibling explicitly, so the differentiation is left for the agent to infer.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no conditions, and no mention of the obvious alternative get_user_latest_post_time. The only contextual remark is about the account default, which is parameter behavior rather than usage routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_pagesB

Search Facebook pages by keyword, e.g. 'pest control'. Requires a logged-in session. Optional account name selecting the credential set under ~/.facebook-mcp/accounts//. Defaults to the configured account.

ParametersJSON Schema
NameRequiredDescriptionDefault
qYes
limitNo
accountNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden. It does disclose meaningful traits — a logged-in session is required and which credential set gets selected — but says nothing about pagination, rate limits, or failure behavior, and 'search' gives no indication of read scope beyond the implicit read.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the purpose, then prerequisite, then the optional parameter detail. No filler, though the ~/.facebook-mcp/accounts/<account>/ path spelling is verbose for what it conveys.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values needn't be explained, and the auth prerequisite is covered. The notable gap is the undocumented 'limit' parameter, which appears in neither the description nor the schema, and no indication of how many results or pagination behavior to expect.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It documents 'q' (with an example) and 'account' (credential path plus default), which is worthwhile, but 'limit' is never mentioned and neither 'q' nor 'account' syntax is fully specified beyond the example.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Search Facebook pages by keyword') and gives a concrete example query. The resource 'pages' implicitly separates it from search_people, but the description never names that sibling or other alternatives, so differentiation is left to inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the purpose plus the stated prerequisite ('Requires a logged-in session'), but there is no explicit when-to-use/when-not guidance and no pointer to alternatives like search_people for a different entity type.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_peopleA

Search Facebook people by keyword, e.g. 'pest control'. Requires a logged-in session. Optional account name selecting the credential set under ~/.facebook-mcp/accounts//. Defaults to the configured account.

ParametersJSON Schema
NameRequiredDescriptionDefault
qYes
limitNo
accountNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden; it usefully discloses the auth requirement (logged-in session) and how credentials resolve via ~/.facebook-mcp/accounts/<account>/ with a configured default. Beyond that it says nothing about result volume, pagination, or rate limits, so disclosure is partial.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with purpose, then prerequisites and the optional account detail. Nothing is wasted, though the long filesystem path could be trimmed for readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained. Purpose, auth prerequisite, and account selection are covered; the only gap is the undocumented 'limit' parameter and any result-count behavior, which is minor for this tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the schema provides no parameter documentation. The description does compensate for 'account' by explaining its credential-directory semantics and default, and it illustrates 'q' with an example, but 'limit' is entirely unaddressed despite its default of 10.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Search Facebook people by keyword') and reinforces it with a concrete query example. It implicitly distinguishes itself from the sibling search_pages, but never names that alternative to remove the ambiguity between searching people vs pages.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is implied by the resource ('Search Facebook people') and a prerequisite is stated ('Requires a logged-in session'), but there is no explicit statement of when to choose this over search_pages or the get_user_* siblings, and no exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_messageA

Send a Messenger message to a user or page. 'recipient' accepts a numeric uid, a username/vanity, or a profile URL. Requires a logged-in browser (FB_TRANSPORT_MODE=auto or cdp). Optional account name selecting the credential set under ~/.facebook-mcp/accounts//. Defaults to the configured account.

ParametersJSON Schema
NameRequiredDescriptionDefault
textYes
accountNo
recipientYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesWhether the message was sent
errorNoError message when ok=False
thread_idNoMessenger thread id
message_idNoSent message id

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full behavioral burden. It usefully discloses the auth/transport prerequisite and where account credentials live, which is real context the schema cannot express. But for a mutation (message-send) tool it omits delivery semantics — immediacy, failure modes, rate limits, or irreversibility — leaving the behavioral picture incomplete.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then recipient syntax, then prerequisites and account default — a logical ordering with little waste. It is slightly verbose (three clauses on transport/account paths) but each clause conveys usable information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described, and the description covers prerequisites, recipient formats, and account selection for a 3-parameter tool. The remaining gap is mutation-side behavior (rate limits, failure handling), which keeps it short of fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate and largely does: it explains that 'recipient' accepts a numeric uid, username/vanity, or profile URL, and that 'account' selects a credential set under ~/.facebook-mcp/accounts/<account>/ and defaults to the configured account. Only 'text' is left undocumented, but its meaning is self-evident.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a concrete verb+resource ('Send a Messenger message to a user or page'), leaving no ambiguity about the operation. It does not reference any sibling tool, but the action is inherently distinct from the read-only siblings (search_people, get_user_recent_posts), so differentiation is implicit rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives prerequisites ('Requires a logged-in browser (FB_TRANSPORT_MODE=auto or cdp)') which effectively tells the agent when the tool can be invoked. However, it never states when to prefer this over alternatives, nor any exclusions (e.g., unsolicited/spam messaging limits or rate limits). Usage is only implied by the tool's obvious purpose.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.1.0
    • First observedget_user_latest_post_time
    • First observedget_user_recent_posts
    • First observedsearch_pages
    • First observedsearch_people
    • First observedsend_message

TDQS

A3.6/5.0

Scored across 5 tools

Disambiguation4/5

search_people, search_pages, and send_message are clearly distinct, and the two retrieval tools target different scopes. However, get_user_latest_post_time is essentially a subset of get_user_recent_posts (which returns newest-first posts with publish times), so an agent may struggle to justify choosing one over the other.

Naming Consistency5/5

All five tools follow a consistent snake_case verb_noun pattern (get_user_*, search_*, send_message). No mixed conventions or vague verbs; the naming is predictable and self-explanatory.

Tool Count4/5

Five tools is a reasonable, well-scoped surface for a Facebook read/search/messaging server. It is on the lean side but each tool earns its place, with no filler.

Completeness3/5

The surface covers reading posts, searching people/pages, and sending messages, but lacks any content-creation (posting, commenting, liking) or message/conversation retrieval, leaving notable gaps for a Facebook interaction server.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    A Model Context Protocol (MCP) server implementation that provides Facebook Page interaction and management capabilities. This server enables automated posting, comment moderation, and content retrieval.
    7
    77
    -
  • A
    license
    B
    quality
    C
    maintenance
    Enables MCP-based interaction with the Meta Graph API for Facebook Pages and linked Instagram Business accounts, including posting, commenting, and reading page details.
    6
    6 npm
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables MCP clients to query public Facebook pages and profiles by handle, retrieving like counts, contact details, owner info, and recent posts with reactions, comments, and shares as structured JSON.
    1
    40 npm
    46 PyPI
    11
    MIT