Skip to main content
Glama
facebook-mcp

facebook-mcp

by IvanBBaev

Post Insights

facebook_post_insights
Read-onlyIdempotent

Read insights for one published Facebook post—media views, clicks, reactions, video metrics—as compact rows and per-metric summaries, with aggregate-only or CSV/JSON export.

Instructions

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 facebook_page_insights: rows plus semantics-aware per-metric summaries (total removed; read value and aggregation), or summaries only with aggregate:true (output:{format} writes every row to a CSV/JSON file instead). The default period is "lifetime" — one cumulative value per metric. Post metrics lag minutes to hours after publishing, so empty series on a fresh post are normal and are flagged as such rather than reported as zeros. Reel metrics are NOT reachable through this tool: they live on /{video-id}/video_insights, a different edge — a Reel ID here returns empty series, never Reel numbers. Use facebook_reel_insights with the VIDEO id instead.

Input Schema

NameRequiredDescriptionDefault
sinceNoInclusive start boundary as a calendar date "YYYY-MM-DD". The range is [since, until); Page period=day boundaries are Pacific Time (America/Los_Angeles), post and Reel boundaries UTC. Omitted ⇒ Graph's own default window. The since..until boundary span may not exceed 90 days per call (checked before the request); read longer histories in slices.
untilNoEXCLUSIVE end boundary as a calendar date "YYYY-MM-DD": for Page period=day, until=2026-08-30 includes the 2026-08-29 Pacific day but not 2026-08-30, and since = until is refused as an empty window. Each returned `date` is Graph's exclusive end boundary of its period, so a window reaching today ends in a partial, still-being-computed bucket. Omitted ⇒ today (Pacific Time for a Page, UTC otherwise).
outputNoWrite the FULL series to a local file in FB_EXPORT_DIR instead of returning rows. The row cap does not apply to the file; the inline result is the aggregate-mode summary (no rows, max_rows and aggregate are ignored) plus `export: {path, format, rows, bytes, sha256}`. Use it for long daily series that would otherwise be truncated.
periodNoAggregation window Graph applies per data point. "day" is a daily series (the Page default); "lifetime" is one cumulative value per metric (the post default); "week"/"days_28" are rolling windows; "month" is calendar-monthly; "total_over_range" collapses since..until into a single value. Not every metric supports every period — a metric queried with an unsupported period comes back empty, which the notes call out.
metricsYesGraph insights metric names to read, e.g. ["page_media_view","page_follows"] (1-20 per call; trimmed and lower-cased). Names are Graph-version dependent and Meta renamed most of them in the 2024-09, 2025-11 and 2026-06 waves: pre-wave names such as "page_impressions" or "page_fans" are dropped before the request and answered with their replacement instead of an error. Graph fails the WHOLE call when one surviving name is invalid: when Graph says which entry it rejected, that name is dropped, the rest are re-read and it is reported in rejectedMetrics; otherwise isolate a suspect name by requesting it alone. Page metrics (page_*) are read on the Page, post metrics (post_*) on a post or Reel.
post_idYesThe published post to read, as Graph's "{page-id}_{post-id}" ID (as returned by facebook_list_posts / facebook_get_post). Permalink URLs and bare numeric IDs are rejected before any request — a bare number is a video/photo ID (see facebook_reel_insights), not a post. The post must belong to the resolved Page, whose token authorizes the read.
profileNoPage profile key (e.g. "brand-a") or a raw Page ID. Omitted ⇒ the default Page (FB_PAGE_ID).
max_rowsNoLower the per-point row cap for this call (1-250; the default and the ceiling are both 250 — this argument can only shrink it). Rows past the cap are dropped and the result reports how many; prefer aggregate:true over a tiny cap when you only need per-metric summaries.
aggregateNoTrue ⇒ return per-metric summaries only and NO per-point rows. Each summary states its `kind` (flow, gauge, unique, unknown) and its `aggregation`, and carries `value` only when one scalar is safe: known flows over disjoint day/month buckets are summed, gauges such as page_follows take the latest value (plus `change`), week/days_28 rolling windows and lifetime counters take the latest window, and unique-audience or unknown day/month series and breakdown maps get aggregation "none" rather than a guess. Use it for wide windows or many metrics when the daily rows would otherwise be truncated.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed9 schema fields changedv0.8.0
    • changedInput schema / properties / aggregate / description
      Previous value: -"True ⇒ return per-metric totals only (period, points, total, first/last boundary) and NO per-point rows. Use it for wide windows or many metrics: it is the cheapest way to stay inside the result budget when a daily series would otherwise be truncated."New value: +"True ⇒ return per-metric summaries only and NO per-point rows. Each summary states its `kind` (flow, gauge, unique, unknown) and its `aggregation`, and carries `value` only when one scalar is safe: known flows over disjoint day/month buckets are summed, gauges such as page_follows take the latest value (plus `change`), week/days_28 rolling windows and lifetime counters take the latest window, and unique-audience or unknown day/month series and breakdown maps get aggregation \"none\" rather than a guess. Use it for wide windows or many metrics when the daily rows would otherwise be truncated."
    • changedInput schema / properties / max_rows / description
      Previous value: -"Lower the per-point row cap for this call (1-250; the default and the ceiling are both 250 — this argument can only shrink it). Rows past the cap are dropped and the result reports how many; prefer aggregate:true over a tiny cap when you only need totals."New value: +"Lower the per-point row cap for this call (1-250; the default and the ceiling are both 250 — this argument can only shrink it). Rows past the cap are dropped and the result reports how many; prefer aggregate:true over a tiny cap when you only need per-metric summaries."
    • changedInput schema / properties / metrics / description
      Previous value: -"Graph insights metric names to read, e.g. [\"page_media_view\",\"page_follows\"] (1-20 per call; trimmed and lower-cased). Names are Graph-version dependent and Meta renamed most of them in the 2024-09, 2025-11 and 2026-06 waves: pre-wave names such as \"page_impressions\" or \"page_fans\" are dropped before the request and answered with their replacement instead of an error. Graph fails the WHOLE call when one surviving name is invalid, so isolate a suspect name by requesting it alone."New value: +"Graph insights metric names to read, e.g. [\"page_media_view\",\"page_follows\"] (1-20 per call; trimmed and lower-cased). Names are Graph-version dependent and Meta renamed most of them in the 2024-09, 2025-11 and 2026-06 waves: pre-wave names such as \"page_impressions\" or \"page_fans\" are dropped before the request and answered with their replacement instead of an error. Graph fails the WHOLE call when one surviving name is invalid: when Graph says which entry it rejected, that name is dropped, the rest are re-read and it is reported in rejectedMetrics; otherwise isolate a suspect name by requesting it alone. Page metrics (page_*) are read on the Page, post metrics (post_*) on a post or Reel."
    • addedInput schema / properties / metrics / items / pattern
      Added value: +"^[^,]+$"
    • addedInput schema / properties / output
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Write the FULL series to a local file in FB_EXPORT_DIR instead of returning rows. The row cap does not apply to the file; the inline result is the aggregate-mode summary (no rows, max_rows and aggregate are ignored) plus `export: {path, format, rows, bytes, sha256}`. Use it for long daily series that would otherwise be truncated.",
      +  "properties": {
      +    "file_name": {
      +      "description": "Optional bare file name (1-80 of A-Z a-z 0-9 . _ -, no path, no leading dot). The extension is added when missing. Omitted ⇒ <scope>-<objectId>-<since>-<until>-<timestamp>. An existing file is never overwritten; a numeric suffix is added instead.",
      +      "pattern": "^[A-Za-z0-9_-][A-Za-z0-9._-]{0,79}$",
      +      "type": "string"
      +    },
      +    "format": {
      +      "description": "File format: \"csv\" (one row per data point, spreadsheet-ready) or \"json\" (the summaries plus every row).",
      +      "enum": [
      +        "csv",
      +        "json"
      +      ],
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "format"
      +  ],
      +  "type": "object"
      +}
    • changedInput schema / properties / post_id / description
      Previous value: -"The published post to read, as Graph's \"{page-id}_{post-id}\" ID (as returned by facebook_list_posts / facebook_get_post). Permalink URLs are rejected. The post must belong to the resolved Page, whose token authorizes the read."New value: +"The published post to read, as Graph's \"{page-id}_{post-id}\" ID (as returned by facebook_list_posts / facebook_get_post). Permalink URLs and bare numeric IDs are rejected before any request — a bare number is a video/photo ID (see facebook_reel_insights), not a post. The post must belong to the resolved Page, whose token authorizes the read."
    • changedInput schema / properties / post_id / pattern
      Previous value: -"^(?=.*\\w)[\\w.-]+$"New value: +"^\\d+(?:_\\d+)?$"
    • changedInput schema / properties / since / description
      Previous value: -"Start of the window as a calendar date \"YYYY-MM-DD\" (inclusive, Page timezone). Omitted ⇒ Graph's own default window. The since..until span may not exceed 90 days per call (checked before the request); read longer histories in slices."New value: +"Inclusive start boundary as a calendar date \"YYYY-MM-DD\". The range is [since, until); Page period=day boundaries are Pacific Time (America/Los_Angeles), post and Reel boundaries UTC. Omitted ⇒ Graph's own default window. The since..until boundary span may not exceed 90 days per call (checked before the request); read longer histories in slices."
    • changedInput schema / properties / until / description
      Previous value: -"End of the window as a calendar date \"YYYY-MM-DD\". Each returned `date` is the END of the period the value covers, so a window reaching today ends in a partial, still-being-computed bucket. Omitted ⇒ today."New value: +"EXCLUSIVE end boundary as a calendar date \"YYYY-MM-DD\": for Page period=day, until=2026-08-30 includes the 2026-08-29 Pacific day but not 2026-08-30, and since = until is refused as an empty window. Each returned `date` is Graph's exclusive end boundary of its period, so a window reaching today ends in a partial, still-being-computed bucket. Omitted ⇒ today (Pacific Time for a Page, UTC otherwise)."
  2. First observedv0.7.0

TDQS

A4.6/5.0
Behavior5/5

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

Beyond the readOnly/idempotent annotations, it discloses real behavioral traits: the flat row-plus-summary return shape, `total` removal and `value`/`aggregation` semantics, the lifetime default period, publishing lag with empty-series flagging instead of zero-filling, and metric-rename handling with a caveat that one invalid name fails the whole Graph call. The Reel edge limitation is a genuine gotcha the annotations could never convey.

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 purpose, then mode contracts, then the Reel exclusion warning, so the most decision-relevant facts come first. It is dense and parenthetical-heavy with some overlap against the schema, but nearly every clause carries a distinct operational fact.

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

Completeness5/5

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

With 9 parameters, a nested output object and no output schema, the description supplies the missing return-shape contract (rows plus per-metric summaries, aggregate-only mode, file export with path/rows/hash) and the failure modes an agent must anticipate. That is exactly the gap the structured fields leave open.

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 100%, so period defaults, the aggregate behavior and the output/export contract are already documented in the schema. The description largely restates them (aggregate:true, output:{format}, lifetime default) and adds little syntactic or value-domain detail the schema doesn't already carry; the stricter post_id/reel-ID distinction also lives in the schema.

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+resource ("Read Graph insights for one published post") and enumerates the metric families it returns, contrasting the shape with facebook_page_insights. It also explicitly excludes Reels and names facebook_reel_insights as the tool for that edge, so an agent can distinguish it from siblings without opening any schema.

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

Usage Guidelines5/5

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

Gives explicit routing rules: use facebook_reel_insights with the VIDEO id for Reels because this tool returns only empty series there; use aggregate:true or output:{format} when the row cap would truncate a long series. It even sets expectations for a fresh post (metrics lag, empty series are normal and flagged), which is a when-not-to-worry condition rather than a silent failure.

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