Skip to main content
Glama
takezoh

meta-horizon-developer-mcp

by takezoh

meta-horizon-developer-mcp

A read-only stdio MCP server for collecting Analytics from the Meta Horizon developer dashboard (developers.meta.com/horizon).

For package structure and trust boundaries, see ARCHITECTURE.md. For development and change rules, see AGENTS.md.

The bundled meta-horizon-developer CLI is for the collection owner only (manual authentication and scheduled collection).

The collector opens the Analytics and Reviews pages in an authenticated browser, observes only successful persisted GraphQL Query responses issued by the Dashboard itself, removes secrets, and stores immutable JSON. It never constructs and replays requests, performs mutations, or fetches arbitrary URLs.

Usage

# 1. Log in manually (cookies remain in the dedicated Chromium profile).
meta-horizon-developer --app-id <APP_ID> --profile-dir .state/meta-horizon-developer/profile auth

# 2. Collect data (cron-friendly; writes one immutable JSON file).
meta-horizon-developer --app-id <APP_ID> --snapshot-dir data/raw/meta-store collect

# 3. Check status.
meta-horizon-developer --app-id <APP_ID> --snapshot-dir data/raw/meta-store status

CLI arguments can also be supplied through environment variables.

Environment variable

Corresponding argument

Needed for

META_HORIZON_APP_ID

--app-id

everything

META_HORIZON_OUTPUT_DIR

--snapshot-dir

everything

META_HORIZON_PROFILE_DIR

--profile-dir

auth / collect / capture-csv

META_HORIZON_CSV_DIR

--csv-dir

capture-csv (defaults next to the profile)

META_HORIZON_LOOKBACK_DAYS

--lookback-days (default: 120)

collect

PLAYWRIGHT_CHROMIUM_EXECUTABLE

Chromium executable

browser operations

Reading a snapshot never needs a profile: status and read resolve without one.

Related MCP server: meta-mcp

MCP

Start it as a stdio MCP server. It takes no startup arguments. The target application and storage location are tool arguments, so one process serves every application and the host that launches it needs no knowledge of its callers.

{
  "mcpServers": {
    "meta-horizon-developer": {
      "command": "/path/to/bin/meta-horizon-developer-mcp"
    }
  }
}

Splitting the server per application would isolate nothing: every instance opens the same Chromium profile and the same cookies, so the only thing separated is app_id, which is not a secret.

Only four tools are exposed:

Tool

Arguments

Returns

meta_horizon_developer_status

app_id, snapshot_dir

latest snapshot health

meta_horizon_developer_collect

app_id, snapshot_dir, profile_dir, lookback_days?

runs a collection

meta_horizon_developer_latest_snapshot

app_id, snapshot_dir

snapshot metadata (not its payload)

meta_horizon_developer_read_operation

operation_name, app_id, snapshot_dir

one allowed Query

User reviews need no separate tool: read them with meta_horizon_developer_read_operation using OCDevManageApplicationReviewsTableQuery.

Authentication, arbitrary URLs, arbitrary operations, mutations, and Cookie/token values are never exposed. Authentication is available only through the CLI because it requires human interaction.

Invariants

  • One process per profile. auth / collect / capture-csv take an exclusive lock and fail immediately with ProfileBusyError if it cannot be acquired.

  • One application per directory. Never write snapshots for a different app_id into a directory that already contains snapshots (AppIdMismatchError).

  • Always pass --password-store=basic. Without a keyring, Chromium may select another key and appear unauthenticated because it cannot decrypt any saved cookies.

  • Separate proxy credentials. Chromium does not use credentials embedded in a proxy URL for CONNECT; passing them that way results in 407 and ERR_TUNNEL_CONNECTION_FAILED.

  • The aggregation period comes from URL start / end. Presets allow at most 28 days, so a custom period (default: 120 days) is passed to the Dashboard to produce a longer daily series.

  • Fail when collection captures zero operations. Do not leave an empty snapshot. Partial gaps are recorded in missing_operations / missing_required_operations.

  • Finish reading a response before leaving its page. Chromium discards the body once the page is gone, and a handler that has not read it yet loses that operation silently.

  • Reviews are read by scrolling, and their authors are dropped before storage. The reviews table has no pager and no period parameter: it extends its GraphQL connection as the inner container is scrolled, so the collector scrolls until has_next_page is false. Every row also carries the reviewer's alias and account id, which name a person and which no secret-key pattern would match, so they are removed at capture time rather than redacted afterwards.

Snapshot format

{
  "schema_version": 1,
  "collected_at": "2026-08-06T01:23:45Z",
  "source": "meta-horizon-dashboard",
  "app_id": "…",
  "operations": [{"name": "…Query", "doc_id": "…", "data": {…}, "errors": null}],
  "missing_operations": ["…"],
  "missing_required_operations": ["…"]
}

Files are named meta-store-<UTC>.json, mode 0600, and are never overwritten.

A scrolled table is many responses merged into one operation, so it is stored as a flat list instead of a GraphQL connection. truncated records that the Dashboard still had more rows when the round limit stopped the scroll — without it a short list would read as "these are all the reviews".

{"name": "OCDevManageApplicationReviewsTableQuery", "doc_id": "…", "errors": null,
 "data": {"rows": [{"id": "…", "date": 1786083632, "score": 5, "title": "…",
                    "description": "…", "helpful_count": 1, "is_down_ranked": false,
                    "developer_tags": [], "app_version": "0.1.10283",
                    "developer_response": "…", "has_moderation_request": false}],
          "truncated": false, "response_count": 20}}

dashboard.json is the contract for the Dashboard pages and allowed operations; it does not identify an application. The page layout is shared across applications, so this allowlist is shared as well. pages are opened with the analytics period; scroll_pages carry no period and are read by scrolling to the end of their table.

Secrets

  • Cookies remain only in the dedicated profile; they are not written to configuration or snapshots.

  • Responses are redacted before storage (authorization / cookie / token / session / email / user_id / dtsg and similar fields).

  • Review authors are dropped at capture time. Redaction matches key names, and the author arrives under alias / id, which no pattern would catch.

  • Profiles and snapshots must never be committed to Git.

Development

uv run --project . pytest -q
uv run --project . ruff check src tests

The package requires Python 3.13 or newer. Runtime state is intentionally excluded from Git.

Available Tools

4 tools
meta_horizon_developer_collectA

Collect allow-listed aggregate GraphQL Queries into a new snapshot.

Requires profile_dir because it drives an authenticated browser. Fails immediately with ProfileBusyError when another process already holds that profile.

ParametersJSON Schema
NameRequiredDescriptionDefault
app_idYes
profile_dirYes
snapshot_dirYes
lookback_daysNo

TDQS

A3.7/5.0
Behavior4/5

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

With no annotations provided, the description carries the full transparency burden. It discloses a prerequisite (authenticated browser via profile_dir) and a specific failure mode (ProfileBusyError when profile is locked), which adds meaningful behavioral context beyond the basic purpose. However, it does not mention other side effects or security requirements.

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?

The description is two sentences and front-loaded with the core purpose. The second sentence adds essential context (prerequisite and error behavior) without any redundancy or filler. Every sentence earns its place.

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

Completeness2/5

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

The tool has 4 parameters, no output schema, and no annotations. The description explains profile_dir and the error case, but leaves app_id, snapshot_dir, lookback_days, and the overall snapshot payload ambiguous. Given the lack of schema descriptions and annotations, the description does not provide enough context to fully understand the tool's behavior.

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

Parameters2/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 for missing parameter meaning. It only explains profile_dir in the context of driving an authenticated browser. app_id, snapshot_dir, and lookback_days are not described in the schema or the description, leaving the agent to guess their roles.

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?

The description clearly states the tool's primary action — 'Collect allow-listed aggregate GraphQL Queries into a new snapshot' — using a specific verb (collect) and resource (GraphQL queries into a snapshot). This distinguishes it from sibling tools like status and read_operation, which serve different purposes.

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 purpose implies when to use the tool (creating a new snapshot), but there is no explicit comparison to alternatives or exclusions. The mention of needing profile_dir and failing with ProfileBusyError provides a prerequisite, but no direct 'use this when...' or 'use this instead of...' guidance.

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

meta_horizon_developer_latest_snapshotB

Return latest snapshot metadata and collection health, not the large payload.

ParametersJSON Schema
NameRequiredDescriptionDefault
app_idYes
snapshot_dirYes

TDQS

B3.3/5.0
Behavior3/5

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

With no annotations provided, the description carries the full burden for behavioral disclosure. It adds useful context that the tool avoids returning a large payload, implying a performance/bandwidth advantage. However, it does not disclose whether the operation is read-only, has side effects, requires auth, or what happens if no snapshot exists.

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?

The description is a single, front-loaded sentence that conveys the core purpose and key limitation (not the large payload). Every word earns its place, achieving maximum conciseness without empty filler.

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

Completeness2/5

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

Given the low complexity (2 params, no output schema), the description should at least explain parameter semantics and when to use the tool. It fails on both counts, leaving critical gaps for correct invocation. The brief mention of metadata/health and payload size is insufficient for a tool with zero schema descriptions.

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

Parameters1/5

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

Schema description coverage is 0%, and the description does not explain the parameters app_id or snapshot_dir. Since both are required, the lack of any semantic guidance means an agent is left guessing their purpose. The description must compensate for the schema gap but does not.

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?

The description clearly states the verb 'Return' and the resource 'latest snapshot metadata and collection health,' and distinguishes itself from returning the large payload. This differentiates it from sibling tools like meta_horizon_developer_read_operation, which likely retrieves the payload itself.

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 implies usage when metadata or health is needed without the heavy payload, but it does not explicitly state when to use this tool versus alternatives like read_operation or collect. No exclusions or alternative tool names are mentioned.

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

meta_horizon_developer_read_operationC

Read one allow-listed aggregate Query from the latest redacted snapshot.

ParametersJSON Schema
NameRequiredDescriptionDefault
app_idYes
snapshot_dirYes
operation_nameYes

TDQS

C2.8/5.0
Behavior2/5

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

No annotations are provided, so the description must disclose behavioral traits. It uses the word 'Read' to imply a safe, non-destructive operation, but it does not describe return formats, error handling, permissions, or side effects. This is minimal disclosure for a read operation.

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?

The description is a single, front-loaded sentence with no superfluous words. It efficiently communicates the verb and object, scoring high on conciseness and structural clarity.

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

Completeness2/5

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

Given the tool has no annotations, no output schema, and three undocumented parameters, the one-sentence description is insufficient for an agent to confidently select and invoke it. It does not explain key terms like 'aggregate Query' or 'redacted snapshot', nor does it describe how parameters interact with the tool's behavior.

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

Parameters2/5

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

The schema has 0% description coverage, and the description does not explicitly explain the three required parameters (operation_name, app_id, snapshot_dir). It hints that 'aggregate Query' relates to the query name and 'latest redacted snapshot' relates to the snapshot source, but it fails to clarify formats or relationships, leaving the agent to infer from parameter names alone.

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 clearly identifies the action ('Read') and the specific resource (a single allow-listed aggregate query from the latest redacted snapshot). It is concise and conveys the core function, though it does not explicitly distinguish this tool from sibling tools like status or collect.

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?

The description provides no guidance on when to use this tool instead of alternatives. It does not mention scenarios, prerequisites, or context where this tool is preferred, leaving the agent without decision support.

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

meta_horizon_developer_statusC

Return latest collection health for one application.

app_id: target application ID. snapshot_dir: directory holding that application's snapshots.

ParametersJSON Schema
NameRequiredDescriptionDefault
app_idYes
snapshot_dirYes

TDQS

C2.9/5.0
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It only states that it returns data, but does not mention whether it is read-only, what happens if the app_id or snapshot_dir is invalid, or any prerequisites. This is a significant gap for a tool that likely performs reads on a collection system.

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?

The description is compact, consisting of a single purpose sentence and two brief parameter annotations. No unnecessary words or repetition, though the parameter definitions could be integrated more elegantly.

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

Completeness2/5

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

The tool has no output schema, so the description should clarify what the returned 'collection health' looks like or how it is structured, but it does not. It also omits failure modes, preconditions, and how it relates to sibling operations like collect or read_operation, leaving the agent under-informed for correct invocation.

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?

The input schema lists parameters with no descriptions, so the description adds basic labels for both: 'app_id: target application ID' and 'snapshot_dir: directory holding that application's snapshots'. These definitions are helpful but shallow, providing no format, constraints, or relationships beyond what a schematic type already implies.

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 clearly states a specific verb ('Return') and resource ('latest collection health for one application'), making the purpose unambiguous. It distinguishes from sibling 'latest_snapshot' by focusing on 'health' rather than snapshot data, though the exact meaning of 'health' is not elaborated.

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?

No guidance is provided on when to use this tool versus the sibling tools like 'meta_horizon_developer_collect' or 'meta_horizon_developer_latest_snapshot'. The description simply states what it does without any contextual advice or exclusions.

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. 4 tool updatesv0.1.0
    • First observedmeta_horizon_developer_collect
    • First observedmeta_horizon_developer_latest_snapshot
    • First observedmeta_horizon_developer_read_operation
    • First observedmeta_horizon_developer_status

TDQS

C2.9/5.0

Scored across 4 tools

Disambiguation2/5

The status and latest_snapshot tools both report collection health, creating ambiguity about which to use. collect and read_operation are clearly distinct, but the overlap between the two status-related tools is confusing.

Naming Consistency2/5

Tool names mix conventions: 'status' and 'latest_snapshot' are noun phrases, while 'collect' and 'read_operation' start with verbs. There is no consistent verb-first or predictable pattern, making it hard to guess the right tool.

Tool Count4/5

With 4 tools, the server is tightly scoped, which is appropriate for a niche developer-oriented MCP. However, the duplicate health functionality between status and latest_snapshot suggests the count could be reduced without losing capability.

Completeness3/5

The core workflow of collecting snapshots and reading operations is covered, but there is no tool to list snapshots, retrieve a specific non-latest snapshot, or manage the snapshot lifecycle. The overlap between status and latest_snapshot also indicates the surface is not fully refined.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    A read-only MCP server for AppDynamics that exposes 12 task-oriented tools to query applications, topology, metrics, snapshots, health rules, anomalies, events, alerting config, analytics events, and dependency maps via OAuth API-client credentials.
    12
    1
    MIT
  • A
    license
    C
    quality
    D
    maintenance
    Read-only MCP server for Meta (Facebook) Graph API, enabling access to Marketing API, Pages, Instagram, and WhatsApp Business data through Claude Code and any MCP-compatible client.
    30
    5 npm
    1
    MIT
  • A
    license
    B
    quality
    B
    maintenance
    Read-only MCP server for Meta Ads that lists and reads ad accounts, campaigns, ad sets, ads, ad images, creatives, and fetches insights at various levels.
    14
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for organic Instagram analytics via the Meta Graph API, providing read-only tools for profiles, media, insights, audience, and optional publishing.
    GPL 3.0