Bitmovin Observability MCP

Query and analyse your data from Bitmovin Observability

Should I use this

Quality & Safety

A
Description quality
100%
Schema completeness
86%
Naming quality
98%
Poisoning risk
100%
Permission match
100%
Protocol compliance
100%

Based on automated analysis of tool definitions and protocol compliance.

Context Cost

~4,361Tokens (tool definitions)
~2.2 KBTypical response size
Significant attention impact (3.41% of 128k context)

This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.

Install

One-Click Install

Add this to your `claude_desktop_config.json` file:

{
  "mcpServers": {
    "analytics-mcp": {
      "url": "https://analytics.mcp.bitmovin.com"
    }
  }
}

Remote endpoints

https://analytics.mcp.bitmovin.comstreamable-http
https://analytics.mcp.bitmovin.comsse

What it can do

Tool inventory

Tools (11)

🟢 Read-only🟡 Write🔴 Delete⚪ Unknown
🟢query(licenseKey, metric, start, end, aggregation, ...)

Query a metric over a time range (start/end) for a license as a TIME SERIES — always renders a chart. Use this for trends and license-wide analytics over a period (e.g. 'last week', 'last 30 days', 'yesterday'). Bucket size is chosen automatically from start/end; there is no interval field to set. For a single aggregated number (one total/average over the whole period, NO chart), use the separate `queryTotal` tool instead. Queries resolve against API metric keywords, which can differ from a metric's common name — 'plays', for example, is 'impression_id'. The 'searchMetrics' tool resolves a keyword cheaply; 'getAvailableMetrics' returns the full catalog. Every query needs a licenseKey; `peekAllLicenses` lists the ones available. AD ANALYTICS: ad metrics use 'ad_'-prefixed keywords and are queried against a separate ads dataset. The ad completion funnel is: 'ad_quartile_1' (first quartile / 25%) -> 'ad_midpoint' (50%) -> 'ad_quartile_3' (third quartile / 75%) -> 'ad_completions'. Other ad metrics: 'ad_impressions', 'ad_starts', 'ad_clicks', 'ad_skips', 'ad_startup_time', 'ad_error_percentage', 'ad_error_sessions', 'ad_time_played', 'ad_play_percentage', 'ad_unique_users'. Ad data is present on some licenses and not others; `peekAllLicenses` output shows which. A query covers a single license, so an ad question resolves against one license at a time. With an ad metric, filters and groupBy take the AD-specific attributes from 'searchFilters' / 'getAvailableFilters' (e.g. 'AD_SYSTEM', 'AD_POSITION', 'ADVERTISER_NAME'); playback attributes and ad attributes are not interchangeable. OPTIONAL 3) Use the 'searchFilters' tool to find filter attributes/operators (or 'getAvailableFilters' for the full list).

Input Schema

{
  "type": "object",
  "properties": {
    "licenseKey": {
      "type": "string",
      "format": "uuid",
      "description": "license key (uuid) to query"
    },
    "metric": {
      "type": "string",
      "description": "the metric to query. before setting a value, resolve the keyword with the `searchMetrics` tool"
    },
    "start": {
      "type": "string",
      "description": "start date/time in ISO 8601 format (e.g., '2025-10-01T00:00:00')"
    },
    "end": {
      "type": "string",
      "description": "end date/time in ISO 8601 format (e.g., '2025-10-02T00:00:00')"
    },
    "aggregation": {
      "type": "string",
      "enum": [
        "count",
        "average",
        "median",
        "percentile",
        "sum"
      ],
      "description": "aggregation method: 'average', 'median', or 'percentile'. If not specified, uses the metric's default aggregation method"
    },
    "percentile": {
      "type": "number",
      "minimum": 0,
      "maximum": 100,
      "description": "percentile value (0-100) - required when aggregation is 'percentile'"
    },
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "category name to filter on"
          },
          "operator": {
            "type": "string",
            "enum": [
              "eq",
              "ne",
              "gt",
              "gte",
              "lt",
              "lte",
              "in",
              "contains"
            ],
            "description": "the filter operator"
          },
          "value": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "array",
                "items": {
                  "type": [
                    "string",
                    "number"
                  ]
                }
              }
            ],
            "description": "the value to filter by. For 'in' operator, provide an array of values"
          }
        },
        "required": [
          "name",
          "operator",
          "value"
        ],
        "additionalProperties": false
      },
      "description": "optional filters to apply to the query"
    }
  },
  "required": [
    "licenseKey",
    "metric",
    "start",
    "end"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🟢queryGroupBy(licenseKey, metric, start, end, groupBy, ...)

query metric grouped by categories. Queries resolve against API metric keywords, which can differ from a metric's common name — 'plays', for example, is 'impression_id'. The 'searchMetrics' tool resolves a keyword cheaply; 'getAvailableMetrics' returns the full catalog. Every query needs a licenseKey; `peekAllLicenses` lists the ones available. AD ANALYTICS: ad metrics use 'ad_'-prefixed keywords and are queried against a separate ads dataset. The ad completion funnel is: 'ad_quartile_1' (first quartile / 25%) -> 'ad_midpoint' (50%) -> 'ad_quartile_3' (third quartile / 75%) -> 'ad_completions'. Other ad metrics: 'ad_impressions', 'ad_starts', 'ad_clicks', 'ad_skips', 'ad_startup_time', 'ad_error_percentage', 'ad_error_sessions', 'ad_time_played', 'ad_play_percentage', 'ad_unique_users'. Ad data is present on some licenses and not others; `peekAllLicenses` output shows which. A query covers a single license, so an ad question resolves against one license at a time. With an ad metric, filters and groupBy take the AD-specific attributes from 'searchFilters' / 'getAvailableFilters' (e.g. 'AD_SYSTEM', 'AD_POSITION', 'ADVERTISER_NAME'); playback attributes and ad attributes are not interchangeable. The groupBy attribute is an exact API attribute name, and common guesses are often wrong: 'OPERATING_SYSTEM' is invalid where 'OPERATINGSYSTEM' is correct, and an unrecognised attribute fails with a validation error. The 'searchFilters' tool resolves an attribute name; 'getAvailableFilters' returns the full catalog. Results grouped by ERROR_CODE carry occurrence counts but not error semantics, which are Bitmovin-specific and documented in the live Bitmovin documentation served by the docs MCP tool (typically `general_docs_ask_bitmovin_docs`). That tool resolves one numeric error code per call and returns nothing usable for a question naming several codes at once.

Input Schema

{
  "type": "object",
  "properties": {
    "licenseKey": {
      "type": "string",
      "format": "uuid",
      "description": "license key (uuid) to query"
    },
    "metric": {
      "type": "string",
      "description": "the metric to query. before setting a value, resolve the keyword with the `searchMetrics` tool"
    },
    "start": {
      "type": "string",
      "description": "start date/time in ISO 8601 format (e.g., '2025-10-01T00:00:00')"
    },
    "end": {
      "type": "string",
      "description": "end date/time in ISO 8601 format (e.g., '2025-10-02T00:00:00')"
    },
    "groupBy": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      ],
      "description": "category (or array of categories) to group results by — e.g. Case-insensitive: ['BROWSER', 'COUNTRY'] or just 'BROWSER'. Prefer an array even for a single value. Use the `searchFilters` tool (pass the licenseKey) to resolve the valid attribute names."
    },
    "aggregation": {
      "type": "string",
      "enum": [
        "count",
        "average",
        "median",
        "percentile",
        "sum"
      ],
      "description": "aggregation method: 'average', 'median', or 'percentile'. If not specified, uses the metric's default aggregation method"
    },
    "percentile": {
      "type": "number",
      "minimum": 0,
      "maximum": 100,
      "description": "percentile value (0-100) - required when aggregation is 'percentile'"
    },
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "category name to filter on"
          },
          "operator": {
            "type": "string",
            "enum": [
              "eq",
              "ne",
              "gt",
              "gte",
              "lt",
              "lte",
              "in",
              "contains"
            ],
            "description": "the filter operator"
          },
          "value": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "array",
                "items": {
                  "type": [
                    "string",
                    "number"
                  ]
                }
              }
            ],
            "description": "the value to filter by. For 'in' operator, provide an array of values"
          }
        },
        "required": [
          "name",
          "operator",
          "value"
        ],
        "additionalProperties": false
      },
      "description": "optional filters to apply to the query"
    }
  },
  "required": [
    "licenseKey",
    "metric",
    "start",
    "end",
    "groupBy"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🟢queryTotal(licenseKey, metric, start, end, aggregation, ...)

Get an aggregated value (one number) for a metric over a time range — no chart, no time bucketing. Can fetch SEVERAL metrics in one call: pass an array to `metric` to get one value per metric (e.g. the ad completion funnel), instead of calling this tool repeatedly. Use ONLY when the user asks for totals/averages/median/p95 over a whole period (e.g. 'total plays last month', 'average startup time yesterday', 'p95 rebuffer last week', 'the ad funnel counts last week'). For trends or any 'how did X change over time' / 'show last week' question, use the `query` tool instead — it always renders a chart. Queries resolve against API metric keywords, which can differ from a metric's common name — 'plays', for example, is 'impression_id'. The 'searchMetrics' tool resolves a keyword cheaply; 'getAvailableMetrics' returns the full catalog. Every query needs a licenseKey; `peekAllLicenses` lists the ones available. AD ANALYTICS: ad metrics use 'ad_'-prefixed keywords and are queried against a separate ads dataset. The ad completion funnel is: 'ad_quartile_1' (first quartile / 25%) -> 'ad_midpoint' (50%) -> 'ad_quartile_3' (third quartile / 75%) -> 'ad_completions'. Other ad metrics: 'ad_impressions', 'ad_starts', 'ad_clicks', 'ad_skips', 'ad_startup_time', 'ad_error_percentage', 'ad_error_sessions', 'ad_time_played', 'ad_play_percentage', 'ad_unique_users'. Ad data is present on some licenses and not others; `peekAllLicenses` output shows which. A query covers a single license, so an ad question resolves against one license at a time. With an ad metric, filters and groupBy take the AD-specific attributes from 'searchFilters' / 'getAvailableFilters' (e.g. 'AD_SYSTEM', 'AD_POSITION', 'ADVERTISER_NAME'); playback attributes and ad attributes are not interchangeable.

Input Schema

{
  "type": "object",
  "properties": {
    "licenseKey": {
      "type": "string",
      "format": "uuid",
      "description": "license key (uuid) to query"
    },
    "metric": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      ],
      "description": "the metric to query: a single keyword, or an array of up to 6 keywords resolved together in one call, which returns one value per metric. A multi-metric ask such as the ad completion funnel is one array — ['ad_quartile_1','ad_midpoint','ad_quartile_3','ad_completions'] — rather than one call each. Keywords are the API's own names, which the `searchMetrics` tool resolves."
    },
    "start": {
      "type": "string",
      "description": "start date/time in ISO 8601 format (e.g., '2025-10-01T00:00:00')"
    },
    "end": {
      "type": "string",
      "description": "end date/time in ISO 8601 format (e.g., '2025-10-02T00:00:00')"
    },
    "aggregation": {
      "type": "string",
      "enum": [
        "count",
        "average",
        "median",
        "percentile",
        "sum"
      ],
      "description": "aggregation method: 'average', 'median', or 'percentile'. If not specified, uses the metric's default aggregation method"
    },
    "percentile": {
      "type": "number",
      "minimum": 0,
      "maximum": 100,
      "description": "percentile value (0-100) - required when aggregation is 'percentile'"
    },
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "category name to filter on"
          },
          "operator": {
            "type": "string",
            "enum": [
              "eq",
              "ne",
              "gt",
              "gte",
              "lt",
              "lte",
              "in",
              "contains"
            ],
            "description": "the filter operator"
          },
          "value": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "array",
                "items": {
                  "type": [
                    "string",
                    "number"
                  ]
                }
              }
            ],
            "description": "the value to filter by. For 'in' operator, provide an array of values"
          }
        },
        "required": [
          "name",
          "operator",
          "value"
        ],
        "additionalProperties": false
      },
      "description": "optional filters to apply to the query"
    }
  },
  "required": [
    "licenseKey",
    "metric",
    "start",
    "end"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🟢peekAllLicenses

View a summary of all available licenses with their recent play counts and percentage distribution. Use this to understand what licenses exist and their relative usage. When a user asks about licenses by ranking (e.g., 'biggest', 'most active', 'first'), use this to identify which license matches that criteria before querying.

Input Schema

{
  "type": "object",
  "properties": {},
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🟢getImpressionOverview(impressionId, licenseKey)

Inspect a SINGLE playback session identified by a specific impressionId. Returns that one session's static properties (device, location, player) and its aggregated metrics (total played time, buffering, video quality). REQUIRES an impressionId. Do NOT use this for license-wide metrics, totals, trends, or any time-range ('last week', start/end) analysis — this tool does not accept start/end. For metrics over a time period use the 'query' tool; for breakdowns by category use 'queryGroupBy'.

Input Schema

{
  "type": "object",
  "properties": {
    "impressionId": {
      "type": "string",
      "description": "Impression ID"
    },
    "licenseKey": {
      "type": "string",
      "format": "uuid",
      "description": "license key (uuid) to query"
    }
  },
  "required": [
    "impressionId",
    "licenseKey"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🟢analyzeImpression(impressionId, licenseKey)

Deep-dive analysis of a SINGLE playback session identified by a specific impressionId: static properties, aggregated metrics, state-transition timeline, and an AI-powered interpretation of session quality. Use for detailed single-session troubleshooting. REQUIRES an impressionId. Do NOT use this for license-wide metrics, totals, trends, or any time-range ('last week', start/end) analysis — this tool does not accept start/end. For metrics over a time period use the 'query' tool; for breakdowns by category use 'queryGroupBy'.

Input Schema

{
  "type": "object",
  "properties": {
    "impressionId": {
      "type": "string",
      "description": "Impression ID"
    },
    "licenseKey": {
      "type": "string",
      "format": "uuid",
      "description": "license key (uuid) to query"
    }
  },
  "required": [
    "impressionId",
    "licenseKey"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🟢fetchImpressions(licenseKey, start, end, filters, limit)

List the impression ids (individual playback session ids) for a license over a time range, optionally narrowed by filters. Returns the ids themselves — NOT counts, totals, or trends. Use this to enumerate sessions before drilling into specific ones with `getImpressionOverview` or `analyzeImpression`. Typical uses: 'give me impression ids from yesterday', 'list sessions on Safari that errored last week', 'sample sessions from country US'. Every matching session is eligible (including failed/setup sessions), not only successful plays. Results are capped (default 100, max 200); if truncated, narrow the timeframe/filters or raise `limit`. A licenseKey is required, and `peekAllLicenses` lists the available ones; `searchFilters` resolves the filter attributes and operators used by the optional `filters` input. For metric counts/trends over a period use `query` / `queryTotal`; for category breakdowns use `queryGroupBy`.

Input Schema

{
  "type": "object",
  "properties": {
    "licenseKey": {
      "type": "string",
      "format": "uuid",
      "description": "license key (uuid) to query"
    },
    "start": {
      "type": "string",
      "description": "start date/time in ISO 8601 format (e.g., '2025-10-01T00:00:00')"
    },
    "end": {
      "type": "string",
      "description": "end date/time in ISO 8601 format (e.g., '2025-10-02T00:00:00')"
    },
    "filters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "category name to filter on"
          },
          "operator": {
            "type": "string",
            "enum": [
              "eq",
              "ne",
              "gt",
              "gte",
              "lt",
              "lte",
              "in",
              "contains"
            ],
            "description": "the filter operator"
          },
          "value": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "array",
                "items": {
                  "type": [
                    "string",
                    "number"
                  ]
                }
              }
            ],
            "description": "the value to filter by. For 'in' operator, provide an array of values"
          }
        },
        "required": [
          "name",
          "operator",
          "value"
        ],
        "additionalProperties": false
      },
      "description": "optional filters to apply to the query"
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 200,
      "description": "maximum number of impression ids to return (1-200, default 100)"
    }
  },
  "required": [
    "licenseKey",
    "start",
    "end"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🟢getAvailableMetrics

List the full catalog of metrics with their supported aggregation methods. Prefer searchMetrics to resolve a single keyword; use this only when you need every metric.

Input Schema

{
  "type": "object",
  "properties": {},
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🟢getAvailableFilters(licenseKey)

List the full catalog of filter attributes with their supported operators. Prefer searchFilters to resolve a single attribute; use this only when you need every filter.

Input Schema

{
  "type": "object",
  "properties": {
    "licenseKey": {
      "type": "string",
      "format": "uuid",
      "description": "license key (uuid) to query"
    }
  },
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🟢searchMetrics(query, limit)

Find the exact metric keyword for a topic or question (e.g. 'buffering', 'how many errors'). Preferred way to resolve a metric keyword; use getAvailableMetrics only to list the full catalog.

Input Schema

{
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "description": "free-text term or question describing the metric/filter you want (e.g., 'buffering', 'browser', 'how many errors')"
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 20,
      "description": "maximum number of results to return (default 5)"
    }
  },
  "required": [
    "query"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🟢searchFilters(query, limit, licenseKey)

Find the exact filter/group-by attribute keyword for a topic or question (e.g. 'browser', 'device type', 'content tier'). Preferred way to resolve an attribute; use 'licenseKey' to resolve custom namings of attributes; use getAvailableFilters only to list the full static catalog.

Input Schema

{
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "description": "free-text term or question describing the metric/filter you want (e.g., 'buffering', 'browser', 'how many errors')"
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 20,
      "description": "maximum number of results to return (default 5)"
    },
    "licenseKey": {
      "type": "string",
      "format": "uuid",
      "description": "license key (uuid) to query"
    }
  },
  "required": [
    "query"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}

Community

Rate this Server

Evidence

Recent observations

verifiedversion not recorded11 tools
verifiedversion not recorded11 tools
verifiedversion not recorded11 tools
verifiedversion not recorded11 tools