Koskamo

gdelt-mcp-server

An MCP server that provides tools to search and analyze global news coverage and US television transcripts using the GDELT Project's real-time APIs. It supports STDIO or Streamable HTTP transports and offers 10 tools for searching articles, tracking coverage timelines, analyzing tone distributions, and breaking down coverage by language, country, or station.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

gdelt-mcp-server logo, by cyanheadsCommunity listingStreamable HTTPNo sign-inEndpoint checked 2026-11-07Published by cyanheads
MCP endpoint (Streamable HTTP)
https://gdelt.caseyjhand.com/mcp
Vendor documentation

What its tools do

10 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.

10 of 10 have a description · 10 of 10 declare behavior hints · 10 of 10 with parameters document them all

Checks and signals

Each line is separate evidence, not a trust score.

  • Passed Endpoint answered the live check ·
  • Availability 1 of 1 checks passed in 30 days

What you can do with it

  • Search recent global news articles using full-text queries and filters
  • Track normalized coverage intensity and sentiment tone over time
  • Analyze tone distribution histograms for news coverage
  • Search television news closed captions and compare station airtime

Source and maintenance

Community listingRegistry 0.8.1
Maintenance checked

Protocol and capabilities

Server
gdelt-mcp-server 0.8.1
MCP protocol negotiated in check
2025-11-25
Tools
10 advertised
Resources
1 advertised
Resource templates
1 advertised
Prompts
0 advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": true
  },
  "logging": {},
  "prompts": {
    "listChanged": true
  },
  "resources": {
    "subscribe": true,
    "listChanged": true
  },
  "extensions": {
    "io.modelcontextprotocol/skills": {
      "directoryRead": true
    }
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

Search recent global news with DOC tools and station-specific television archives with TV tools; no API key is required. Resolve theme operators with gdelt_search_themes and station IDs and monitoring dates with gdelt_list_tv_stations before filtering. Investigate recent spikes with gdelt_get_coverage_timeline, then inspect article evidence; investigate historical TV with gdelt_search_tv, then gdelt_get_tv_clips. Article search and timespan cover the last three months; explicit dates reach older windows in the volume and tone timelines, the language and country breakdowns, and the tone distribution. TV coverage varies by station, so verify the requested dates before interpreting absence. DOC and TV requests share pacing of at least five seconds; theme lookup uses a separate host. Follow pagination and continuation notices before claiming completeness. Where the server keeps a local GKG mirror, DOC tools may answer from it when the DOC API refuses a request or returns nothing, and mark those answers source: gkg_mirror.

Tools

10 advertised

gdelt_search_articles — Search GDELT Articles
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Search the last 3 months of global news coverage (65+ languages) using the GDELT DOC API. Fetches up to 250 articles with URL, title, source domain, language, country, publication date, and social image URL, and returns every fetched article inside the requested window. Query supports full GDELT syntax: phrases ("bird flu"), boolean OR ((flu OR pandemic)), source country (sourcecountry:china), source language (sourcelang:spanish), domain (domain:who.int), GKG theme (theme:TAX_DISEASE_OUTBREAK — find identifiers with gdelt_search_themes), tone filter (tone<-5 for negative), proximity (near20:"flu virus"), and repeat (repeat3:"outbreak"). 250 is a hard per-call ceiling and GDELT offers no cursor: when a query fills it, re-query narrower startDatetime/endDatetime windows — the response hands back the exact windows to use. Note: this API covers only the most recent 3 months — use gdelt_search_tv for historical TV transcripts back to 2009.

gdelt_search_articles input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "query"
  ],
  "properties": {
    "sort": {
      "enum": [
        "relevance",
        "dateDesc",
        "dateAsc",
        "toneDesc",
        "toneAsc",
        "hybridRel"
      ],
      "type": "string",
      "default": "relevance",
      "description": "Sort order: relevance (default), dateDesc/dateAsc, toneDesc/toneAsc, or hybridRel (GDELT hybrid relevance and recency)."
    },
    "query": {
      "type": "string",
      "minLength": 1,
      "description": "Search query. Supports GDELT operators: phrases (\"bird flu\"), boolean OR ((flu OR pandemic)), sourcecountry:china, sourcelang:spanish, domain:who.int, theme:TAX_DISEASE_OUTBREAK (GKG theme identifiers come from gdelt_search_themes), tone<-5, near20:\"flu virus\", repeat3:\"outbreak\"."
    },
    "timespan": {
      "type": "string",
      "description": "Time window relative to now, minimum \"15min\"; other examples: \"24h\", \"7d\", \"1m\". Ignored when startDatetime/endDatetime are set. Maximum is 3 months (the full DOC API window). Defaults to the full 3-month window."
    },
    "maxRecords": {
      "type": "number",
      "default": 75,
      "minimum": 1,
      "multipleOf": 1,
      "description": "Maximum number of articles to fetch. Defaults to 75; values above 250 run at 250 with a limitClamp disclosure unless clamping is disabled. Every fetched in-window record is returned. 250 is GDELT's hard per-call ceiling, with no cursor; split a query that fills it into narrower startDatetime/endDatetime windows."
    },
    "endDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "End of date range in GDELT format YYYYMMDDHHMMSS — exactly 14 digits, no separators (e.g. 20240131235959). Must be supplied together with startDatetime; supplying only one of the two is rejected."
    },
    "startDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "Start of date range in GDELT format YYYYMMDDHHMMSS — exactly 14 digits, no separators (e.g. 20240101000000). Must be supplied together with endDatetime; supplying only one of the two is rejected."
    }
  },
  "additionalProperties": false
}
gdelt_search_articles output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "articles",
        "effectiveQuery",
        "totalCount"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "invalid_date_range",
                "invalid_query",
                "gdelt_rate_limited",
                "gdelt_unavailable"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `invalid_date_range`: Only one of startDatetime / endDatetime was supplied, one of them is not a real UTC calendar timestamp, or startDatetime is not earlier than endDatetime. `invalid_query`: GDELT rejected the query string as malformed — bad keyword length, unbalanced parentheses, or an illegal character. `gdelt_rate_limited`: GDELT rejected the request for its one-request-per-five-seconds limit, or too many requests were already queued for this one to start in time. `gdelt_unavailable`: GDELT DOC API is unreachable or temporarily returned no usable data. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "notice": {
      "type": "string",
      "description": "Guidance on an incomplete or empty result. When no articles matched, how to broaden the query or window. When GDELT returned articles dated outside an explicit startDatetime/endDatetime window, how many were dropped. When the maxRecords cap was reached, raise maxRecords below the 250 ceiling or narrow the date window at it. When the server's local GKG mirror answered (source: gkg_mirror), why, and how its answer differs from the DOC API's. Absent when a non-empty result set from the DOC API is below the cap and no article was dropped as out of window."
    },
    "source": {
      "enum": [
        "doc_api",
        "gkg_mirror"
      ],
      "type": "string",
      "description": "Where this answer came from: doc_api, the GDELT DOC API, or gkg_mirror, the server's local mirror of GDELT's Global Knowledge Graph, which answers when the DOC API refuses the request or returns nothing. Present on every answer while the server runs a mirror; absent otherwise."
    },
    "articles": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "url",
          "title",
          "seendate",
          "domain",
          "language",
          "sourcecountry"
        ],
        "properties": {
          "url": {
            "type": "string",
            "description": "Article URL."
          },
          "title": {
            "type": "string",
            "description": "Article title."
          },
          "domain": {
            "type": "string",
            "description": "Source domain (e.g. \"nytimes.com\")."
          },
          "language": {
            "type": "string",
            "description": "Article language (e.g. \"English\", \"Spanish\")."
          },
          "seendate": {
            "type": "string",
            "description": "Publication datetime in GDELT format (YYYYMMDDTHHMMSSZ)."
          },
          "socialimage": {
            "type": "string",
            "description": "Social sharing image URL when provided by the source."
          },
          "sourcecountry": {
            "type": "string",
            "description": "Country of the source outlet (e.g. \"United States\")."
          }
        },
        "description": "A single news article with metadata.",
        "additionalProperties": false
      },
      "description": "Matching articles sorted per the sort parameter."
    },
    "attempts": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "source",
          "outcome"
        ],
        "properties": {
          "detail": {
            "type": "string",
            "description": "Why, when the outcome has a reason: DOC's failure message or the mirror's."
          },
          "source": {
            "enum": [
              "doc_api",
              "gkg_mirror"
            ],
            "type": "string",
            "description": "The source tried."
          },
          "outcome": {
            "enum": [
              "answered",
              "empty",
              "rate_limited",
              "unavailable",
              "not_ready",
              "not_compiled",
              "outside_coverage",
              "store_error"
            ],
            "type": "string",
            "description": "What the source did: answered, empty (answered with no matches), rate_limited, or unavailable; or why the mirror could not answer: not_ready (no completed sync), not_compiled (the query or its timespan is in a form the mirror cannot evaluate), outside_coverage (the window lies outside the days it holds), store_error."
          }
        },
        "description": "One source's outcome for this call.",
        "additionalProperties": false
      },
      "description": "Each source tried for this call, in order. Present only when the DOC API did not answer with data and the mirror was consulted."
    },
    "coverage": {
      "type": "object",
      "required": [
        "requestedStart",
        "requestedEnd",
        "answeredStart",
        "answeredEnd",
        "missingSlots"
      ],
      "properties": {
        "answeredEnd": {
          "type": "string",
          "description": "End of the window the mirror answered, ISO 8601 UTC."
        },
        "missingSlots": {
          "type": "number",
          "description": "15-minute GKG slots inside the answered window that the mirror holds no data for."
        },
        "requestedEnd": {
          "type": "string",
          "description": "End of the requested window, ISO 8601 UTC."
        },
        "answeredStart": {
          "type": "string",
          "description": "Start of the window the mirror answered, ISO 8601 UTC."
        },
        "requestedStart": {
          "type": "string",
          "description": "Start of the requested window, ISO 8601 UTC."
        }
      },
      "description": "Present only when the mirror answered less than the requested window. Every count, share, and article in this response comes from answeredStart through answeredEnd; nothing outside it, or in a missing slot, was counted.",
      "additionalProperties": false
    },
    "timespan": {
      "type": "string",
      "description": "Echoed timespan parameter when provided."
    },
    "limitClamp": {
      "type": "object",
      "required": [
        "parameter",
        "requested",
        "applied"
      ],
      "properties": {
        "applied": {
          "type": "number",
          "description": "The per-call cap the call ran with instead."
        },
        "parameter": {
          "enum": [
            "maxRecords",
            "limit"
          ],
          "type": "string",
          "description": "The count input that was clamped."
        },
        "requested": {
          "type": "number",
          "description": "The value the call asked for."
        }
      },
      "description": "Present only when the requested count exceeded the per-call cap: the call ran exactly as a call at the cap, and every count, notice, and continuation in this response reflects the applied value.",
      "additionalProperties": false
    },
    "totalCount": {
      "type": "number",
      "description": "Number of articles returned in this response."
    },
    "staleResponse": {
      "type": "object",
      "required": [
        "fetchedAt",
        "ageSeconds",
        "reason"
      ],
      "properties": {
        "reason": {
          "enum": [
            "gdelt_rate_limited",
            "gdelt_unavailable",
            "gdelt_empty"
          ],
          "type": "string",
          "description": "Why the refetch was not used: GDELT rate-limited it, did not answer with data, or answered empty — which GDELT also does under load."
        },
        "fetchedAt": {
          "type": "string",
          "description": "ISO 8601 time GDELT returned the stored answer."
        },
        "ageSeconds": {
          "type": "number",
          "description": "Age of the stored answer when served, in whole seconds."
        }
      },
      "description": "Present only when the refetch of this exact request was refused, failed, or came back empty, and the response is GDELT's stored answer from fetchedAt instead. It holds nothing published after fetchedAt; a relative timespan covers the window ending at fetchedAt, not now. Absent on a live answer.",
      "additionalProperties": false
    },
    "effectiveQuery": {
      "type": "string",
      "description": "Echoed query string for use in follow-up calls."
    },
    "continuationWindows": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "startDatetime",
          "endDatetime"
        ],
        "properties": {
          "endDatetime": {
            "type": "string",
            "description": "End of this window in GDELT format YYYYMMDDHHMMSS."
          },
          "startDatetime": {
            "type": "string",
            "description": "Start of this window in GDELT format YYYYMMDDHHMMSS."
          }
        },
        "description": "One window to re-query with the same query string.",
        "additionalProperties": false
      },
      "description": "Windows to re-run this query against when maxRecords reaches its 250 ceiling: the queried window halved, overlapping by one second so no article falls through the seam. De-duplicate by url. Absent when no window is known or narrowing cannot reach further articles."
    }
  },
  "additionalProperties": false
}
gdelt_search_articles annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
gdelt_get_coverage_timeline — Get GDELT Coverage Timeline
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Retrieve a time series showing when news coverage of a topic spiked, or how average tone shifted over time. Use mode "volume" for normalized coverage intensity (% of all global coverage per timestep). Use "volume_raw" for distinct matching-article counts per timestep and norm, the unsmoothed monitored-article denominator; smoothed counts are moving averages. Use mode "volume_with_articles" for the same signal plus the top articles that drove each spike — this is the primary signal-detection mode: a single call reveals both the spike and its cause, avoiding a follow-up gdelt_search_articles call. Use mode "tone" for average sentiment score per timestep (negative = hostile/fearful, positive = celebratory). Date resolution is inferred from returned intervals: 15 minutes or hours for short windows, days for longer ones. In volume_with_articles mode each timestep carries its first 3 article links and referenceCount, the number of references GDELT supplied (up to ten), not all matching articles; name timesteps' dates in points to get only those timesteps, each with its full supplied list. A response carries limit timesteps (default 10, cap 400); when more remain it returns nextOffset — pass it back as offset with otherwise identical inputs for the next page. Explicit startDatetime/endDatetime windows may predate the last 3 months in "volume" and "tone" modes; "volume_raw" and "volume_with_articles" cover only the last 3 months.

gdelt_get_coverage_timeline input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "query"
  ],
  "properties": {
    "mode": {
      "enum": [
        "volume",
        "volume_raw",
        "volume_with_articles",
        "tone"
      ],
      "type": "string",
      "default": "volume",
      "description": "Timeline mode: \"volume\" returns normalized coverage % per timestep, \"volume_raw\" returns distinct matching-article counts (moving averages when smoothed) and the unsmoothed monitored denominator norm, \"volume_with_articles\" returns volume plus top articles per spike (best for signal detection), \"tone\" returns average sentiment score per timestep."
    },
    "limit": {
      "type": "number",
      "default": 10,
      "minimum": 1,
      "multipleOf": 1,
      "description": "Maximum timesteps per page (default 10, cap 400). Larger counts clamp to 400 unless GDELT_CLAMP_LIMITS=false."
    },
    "query": {
      "type": "string",
      "minLength": 1,
      "description": "Search query using GDELT syntax. Same operators as gdelt_search_articles: phrases, boolean OR, sourcecountry:, sourcelang:, domain:, theme: (GKG theme identifiers come from gdelt_search_themes), tone<."
    },
    "offset": {
      "type": "integer",
      "default": 0,
      "maximum": 9007199254740991,
      "minimum": 0,
      "description": "Zero-based timestep offset — into the timeline, or into the timesteps named in points. Pass nextOffset from the preceding response, with otherwise identical inputs, to get the next page."
    },
    "points": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Timestep dates to return alone, e.g. [\"2024-01-05T12:00:00Z\"]. Take them verbatim from series[].data[].date in a prior response, or from the list an unknown_point error prints. The response then carries only these timesteps, in timeline order, and in volume_with_articles mode each carries its complete article list instead of the first 3. A date matching no timestep is rejected rather than silently ignored."
    },
    "timespan": {
      "type": "string",
      "description": "Time window relative to now, minimum \"15min\"; other examples: \"24h\", \"7d\", \"1m\". Ignored when startDatetime/endDatetime are set. Maximum 3 months."
    },
    "smoothing": {
      "type": "integer",
      "maximum": 30,
      "minimum": 0,
      "description": "Trailing moving-average width in timesteps (0–30; 0 or 1 leaves values unsmoothed). Width N needs N source steps, omitting leading steps without a full window and potentially shifting peaks later."
    },
    "endDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "End datetime in GDELT format YYYYMMDDHHMMSS — exactly 14 digits, no separators (e.g. 20240131235959). Must pair with startDatetime; supplying only one of the two is rejected. In \"volume\" and \"tone\" modes the window may predate the last 3 months; \"volume_raw\" and \"volume_with_articles\" cover only the last 3 months."
    },
    "startDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "Start datetime in GDELT format YYYYMMDDHHMMSS — exactly 14 digits, no separators (e.g. 20240101000000). Must pair with endDatetime; supplying only one of the two is rejected. In \"volume\" and \"tone\" modes the window may predate the last 3 months; \"volume_raw\" and \"volume_with_articles\" cover only the last 3 months."
    }
  },
  "additionalProperties": false
}
gdelt_get_coverage_timeline output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "series",
        "effectiveQuery",
        "mode",
        "totalCount"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "mode": {
      "enum": [
        "volume",
        "volume_raw",
        "volume_with_articles",
        "tone"
      ],
      "type": "string",
      "description": "Timeline mode used for this response."
    },
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "unknown_point",
                "offset_out_of_range",
                "invalid_date_range",
                "invalid_query",
                "gdelt_rate_limited",
                "gdelt_unavailable"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `unknown_point`: A date passed in the points input matches no timestep in a non-empty timeline. `offset_out_of_range`: The requested offset is at or beyond the last timestep of a non-empty timeline, or of the timesteps named in points. `invalid_date_range`: Only one of startDatetime / endDatetime was supplied, one of them is not a real UTC calendar timestamp, or startDatetime is not earlier than endDatetime. `invalid_query`: GDELT rejected the query string as malformed — bad keyword length, unbalanced parentheses, or an illegal character. `gdelt_rate_limited`: GDELT rejected the request for its one-request-per-five-seconds limit, or too many requests were already queued for this one to start in time. `gdelt_unavailable`: GDELT DOC API is unreachable or temporarily returned no usable data. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "notice": {
      "type": "string",
      "description": "Guidance when the query matched no coverage in the window — how to broaden the query or extend the window — or, when this response is one page of several, which timesteps it returned out of how many. When the server's local GKG mirror answered (source: gkg_mirror), why, and how its figures differ from the DOC API's. Absent when the DOC API answered and the whole timeline fit in one response."
    },
    "series": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "label",
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "date",
                "value"
              ],
              "properties": {
                "date": {
                  "type": "string",
                  "description": "Timestep in ISO 8601 format."
                },
                "norm": {
                  "type": "number",
                  "description": "Total articles monitored at this timestep, unsmoothed even when value is smoothed. Present only in volume_raw mode."
                },
                "value": {
                  "type": "number",
                  "description": "Normalized coverage % (volume or volume_with_articles), distinct matching-article count (volume_raw; a moving average when smoothed), or average tone score (tone mode). Tone range is approximately -100 to +100."
                },
                "articles": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "url",
                      "title"
                    ],
                    "properties": {
                      "url": {
                        "type": "string",
                        "description": "Article URL."
                      },
                      "title": {
                        "type": "string",
                        "description": "Article title."
                      }
                    },
                    "description": "An article linked to this spike.",
                    "additionalProperties": false
                  },
                  "description": "Top articles driving coverage at this timestep — the first 3, or all of them for a timestep named in points. Present only in volume_with_articles mode."
                },
                "referenceCount": {
                  "type": "number",
                  "description": "Number of article references GDELT supplied for this timestep (up to ten), not all matching articles; articles carries the first 3 unless the timestep was named in points. Present whenever articles is."
                }
              },
              "description": "A single time-series data point.",
              "additionalProperties": false
            },
            "description": "Time-ordered data points of this series returned in this response."
          },
          "peak": {
            "type": "object",
            "required": [
              "date",
              "value"
            ],
            "properties": {
              "date": {
                "type": "string",
                "description": "Timestep of the peak, in ISO 8601 format."
              },
              "norm": {
                "type": "number",
                "description": "Unsmoothed monitored-article denominator at the peak in volume_raw mode."
              },
              "value": {
                "type": "number",
                "description": "Value at the peak timestep."
              }
            },
            "description": "The point of the whole series with the largest absolute value, across every page — it may lie outside data. Omitted when the series has no points.",
            "additionalProperties": false
          },
          "label": {
            "type": "string",
            "description": "Series label (e.g. \"Volume Intensity\" or \"Average Tone\")."
          },
          "pointCount": {
            "type": "number",
            "description": "Data points in the whole series, across every page — not only those in data. Present whenever the series has points."
          }
        },
        "description": "A single time series with a label and data points.",
        "additionalProperties": false
      },
      "description": "One or more time series (typically one for volume/tone), holding the timesteps of this page."
    },
    "source": {
      "enum": [
        "doc_api",
        "gkg_mirror"
      ],
      "type": "string",
      "description": "Where this answer came from: doc_api, the GDELT DOC API, or gkg_mirror, the server's local mirror of GDELT's Global Knowledge Graph, which answers when the DOC API refuses the request or returns nothing. Present on every answer while the server runs a mirror; absent otherwise."
    },
    "attempts": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "source",
          "outcome"
        ],
        "properties": {
          "detail": {
            "type": "string",
            "description": "Why, when the outcome has a reason: DOC's failure message or the mirror's."
          },
          "source": {
            "enum": [
              "doc_api",
              "gkg_mirror"
            ],
            "type": "string",
            "description": "The source tried."
          },
          "outcome": {
            "enum": [
              "answered",
              "empty",
              "rate_limited",
              "unavailable",
              "not_ready",
              "not_compiled",
              "outside_coverage",
              "store_error"
            ],
            "type": "string",
            "description": "What the source did: answered, empty (answered with no matches), rate_limited, or unavailable; or why the mirror could not answer: not_ready (no completed sync), not_compiled (the query or its timespan is in a form the mirror cannot evaluate), outside_coverage (the window lies outside the days it holds), store_error."
          }
        },
        "description": "One source's outcome for this call.",
        "additionalProperties": false
      },
      "description": "Each source tried for this call, in order. Present only when the DOC API did not answer with data and the mirror was consulted."
    },
    "coverage": {
      "type": "object",
      "required": [
        "requestedStart",
        "requestedEnd",
        "answeredStart",
        "answeredEnd",
        "missingSlots"
      ],
      "properties": {
        "answeredEnd": {
          "type": "string",
          "description": "End of the window the mirror answered, ISO 8601 UTC."
        },
        "missingSlots": {
          "type": "number",
          "description": "15-minute GKG slots inside the answered window that the mirror holds no data for."
        },
        "requestedEnd": {
          "type": "string",
          "description": "End of the requested window, ISO 8601 UTC."
        },
        "answeredStart": {
          "type": "string",
          "description": "Start of the window the mirror answered, ISO 8601 UTC."
        },
        "requestedStart": {
          "type": "string",
          "description": "Start of the requested window, ISO 8601 UTC."
        }
      },
      "description": "Present only when the mirror answered less than the requested window. Every count, share, and article in this response comes from answeredStart through answeredEnd; nothing outside it, or in a missing slot, was counted.",
      "additionalProperties": false
    },
    "limitClamp": {
      "type": "object",
      "required": [
        "parameter",
        "requested",
        "applied"
      ],
      "properties": {
        "applied": {
          "type": "number",
          "description": "The per-call cap the call ran with instead."
        },
        "parameter": {
          "enum": [
            "maxRecords",
            "limit"
          ],
          "type": "string",
          "description": "The count input that was clamped."
        },
        "requested": {
          "type": "number",
          "description": "The value the call asked for."
        }
      },
      "description": "Present only when the requested count exceeded the per-call cap: the call ran exactly as a call at the cap, and every count, notice, and continuation in this response reflects the applied value.",
      "additionalProperties": false
    },
    "nextOffset": {
      "type": "number",
      "description": "Offset of the next page, for the same inputs. Absent when this page reaches the last timestep."
    },
    "totalCount": {
      "type": "number",
      "description": "Total number of data points across all series of the full timeline, not this page."
    },
    "endDatetime": {
      "type": "string",
      "description": "Echoed end datetime when provided (YYYYMMDDHHMMSS)."
    },
    "staleResponse": {
      "type": "object",
      "required": [
        "fetchedAt",
        "ageSeconds",
        "reason"
      ],
      "properties": {
        "reason": {
          "enum": [
            "gdelt_rate_limited",
            "gdelt_unavailable",
            "gdelt_empty"
          ],
          "type": "string",
          "description": "Why the refetch was not used: GDELT rate-limited it, did not answer with data, or answered empty — which GDELT also does under load."
        },
        "fetchedAt": {
          "type": "string",
          "description": "ISO 8601 time GDELT returned the stored answer."
        },
        "ageSeconds": {
          "type": "number",
          "description": "Age of the stored answer when served, in whole seconds."
        }
      },
      "description": "Present only when the refetch of this exact request was refused, failed, or came back empty, and the response is GDELT's stored answer from fetchedAt instead. It holds nothing published after fetchedAt; a relative timespan covers the window ending at fetchedAt, not now. Absent on a live answer.",
      "additionalProperties": false
    },
    "startDatetime": {
      "type": "string",
      "description": "Echoed start datetime when provided (YYYYMMDDHHMMSS)."
    },
    "dateResolution": {
      "enum": [
        "15min",
        "hour",
        "day"
      ],
      "type": "string",
      "description": "Temporal resolution of the data points — 15min, hour, or day — inferred from the spacing of the returned timesteps. Omitted when fewer than two distinct timesteps came back."
    },
    "effectiveQuery": {
      "type": "string",
      "description": "Echoed query string for use in follow-up calls."
    },
    "expandedPoints": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Timestep dates this response is restricted to, each carrying its full article list — echoing the points input. Omitted when points was not supplied."
    }
  },
  "additionalProperties": false
}
gdelt_get_coverage_timeline annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
gdelt_get_tone_distribution — Get GDELT Tone Distribution
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Get the tonal distribution of articles matching a query as a histogram (bins approximately -30 to +30). Unlike a single average tone score, the histogram reveals whether coverage is uniformly negative, bimodal (some articles extremely positive and some extremely negative), or clustered near neutral. Each bin carries its first 3 representative article links and referenceCount, how many GDELT returned; name bins in the bins input to get only those bins, each with every link. A response carries limit bins (default 10, cap 400); when more remain it returns nextOffset — pass it back as offset with otherwise identical inputs for the next page. Distinct from gdelt_get_coverage_timeline (mode: tone) — this is a snapshot distribution across all matching articles, not a time series. Use gdelt_get_coverage_timeline with mode "tone" to see how sentiment shifted over time.

gdelt_get_tone_distribution input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "query"
  ],
  "properties": {
    "bins": {
      "type": "array",
      "items": {
        "type": "integer",
        "maximum": 9007199254740991,
        "minimum": -9007199254740991
      },
      "description": "Tone bins to return alone, e.g. [-7, 4]. Take them from histogram[].bin in a prior response, or from the list an unknown_bin error prints. The response then carries only these bins, in histogram order, each with every representative article link instead of the first 3. A value matching no bin is rejected rather than silently ignored."
    },
    "limit": {
      "type": "number",
      "default": 10,
      "minimum": 1,
      "multipleOf": 1,
      "description": "Maximum bins per page (default 10, cap 400). Larger counts clamp to 400 unless GDELT_CLAMP_LIMITS=false."
    },
    "query": {
      "type": "string",
      "minLength": 1,
      "description": "Search query using GDELT syntax. Same operators as gdelt_search_articles: phrases, boolean OR, sourcecountry:, sourcelang:, domain:, theme: (GKG theme identifiers come from gdelt_search_themes)."
    },
    "offset": {
      "type": "integer",
      "default": 0,
      "maximum": 9007199254740991,
      "minimum": 0,
      "description": "Zero-based bin offset — into the histogram, or into the bins named in bins. Pass nextOffset from the preceding response, with otherwise identical inputs, to get the next page."
    },
    "timespan": {
      "type": "string",
      "description": "Time window relative to now, minimum \"15min\"; other examples: \"24h\", \"7d\", \"1m\". Ignored when startDatetime/endDatetime are set. Maximum 3 months."
    },
    "endDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "End datetime in GDELT format YYYYMMDDHHMMSS — exactly 14 digits, no separators (e.g. 20240131235959). Must pair with startDatetime; supplying only one of the two is rejected. The window may predate the last 3 months."
    },
    "startDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "Start datetime in GDELT format YYYYMMDDHHMMSS — exactly 14 digits, no separators (e.g. 20240101000000). Must pair with endDatetime; supplying only one of the two is rejected. The window may predate the last 3 months."
    }
  },
  "additionalProperties": false
}
gdelt_get_tone_distribution output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "histogram",
        "summary",
        "effectiveQuery",
        "totalCount"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "unknown_bin",
                "offset_out_of_range",
                "invalid_date_range",
                "invalid_query",
                "gdelt_rate_limited",
                "gdelt_unavailable"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `unknown_bin`: A value passed in the bins input matches no bin in a non-empty histogram. `offset_out_of_range`: The requested offset is at or beyond the last bin of a non-empty histogram, or of the bins named in bins. `invalid_date_range`: Only one of startDatetime / endDatetime was supplied, one of them is not a real UTC calendar timestamp, or startDatetime is not earlier than endDatetime. `invalid_query`: GDELT rejected the query string as malformed — bad keyword length, unbalanced parentheses, or an illegal character. `gdelt_rate_limited`: GDELT rejected the request for its one-request-per-five-seconds limit, or too many requests were already queued for this one to start in time. `gdelt_unavailable`: GDELT DOC API is unreachable or temporarily returned no usable data. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "notice": {
      "type": "string",
      "description": "Guidance when no articles matched in the window — how to broaden the query or extend the window — or, when this response is one page of several, which bins it returned out of how many. When the server's local GKG mirror answered (source: gkg_mirror), why, and how its figures differ from the DOC API's. Absent when the DOC API answered and the whole histogram fit in one response."
    },
    "source": {
      "enum": [
        "doc_api",
        "gkg_mirror"
      ],
      "type": "string",
      "description": "Where this answer came from: doc_api, the GDELT DOC API, or gkg_mirror, the server's local mirror of GDELT's Global Knowledge Graph, which answers when the DOC API refuses the request or returns nothing. Present on every answer while the server runs a mirror; absent otherwise."
    },
    "summary": {
      "type": "object",
      "properties": {
        "neutralPct": {
          "type": "number",
          "description": "Percentage of articles in the near-neutral range (bins -2 to +2). Omitted when the histogram counts no articles."
        },
        "peakNegativeBin": {
          "type": "number",
          "description": "Tone bin with the highest count among negative bins (bin < 0). Omitted when no negative bin was returned."
        },
        "peakPositiveBin": {
          "type": "number",
          "description": "Tone bin with the highest count among positive bins (bin > 0). Omitted when no positive bin was returned."
        }
      },
      "description": "Summary statistics derived from the whole histogram, not this page. Each value is omitted when the histogram cannot support it — all of them on an empty result.",
      "additionalProperties": false
    },
    "attempts": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "source",
          "outcome"
        ],
        "properties": {
          "detail": {
            "type": "string",
            "description": "Why, when the outcome has a reason: DOC's failure message or the mirror's."
          },
          "source": {
            "enum": [
              "doc_api",
              "gkg_mirror"
            ],
            "type": "string",
            "description": "The source tried."
          },
          "outcome": {
            "enum": [
              "answered",
              "empty",
              "rate_limited",
              "unavailable",
              "not_ready",
              "not_compiled",
              "outside_coverage",
              "store_error"
            ],
            "type": "string",
            "description": "What the source did: answered, empty (answered with no matches), rate_limited, or unavailable; or why the mirror could not answer: not_ready (no completed sync), not_compiled (the query or its timespan is in a form the mirror cannot evaluate), outside_coverage (the window lies outside the days it holds), store_error."
          }
        },
        "description": "One source's outcome for this call.",
        "additionalProperties": false
      },
      "description": "Each source tried for this call, in order. Present only when the DOC API did not answer with data and the mirror was consulted."
    },
    "coverage": {
      "type": "object",
      "required": [
        "requestedStart",
        "requestedEnd",
        "answeredStart",
        "answeredEnd",
        "missingSlots"
      ],
      "properties": {
        "answeredEnd": {
          "type": "string",
          "description": "End of the window the mirror answered, ISO 8601 UTC."
        },
        "missingSlots": {
          "type": "number",
          "description": "15-minute GKG slots inside the answered window that the mirror holds no data for."
        },
        "requestedEnd": {
          "type": "string",
          "description": "End of the requested window, ISO 8601 UTC."
        },
        "answeredStart": {
          "type": "string",
          "description": "Start of the window the mirror answered, ISO 8601 UTC."
        },
        "requestedStart": {
          "type": "string",
          "description": "Start of the requested window, ISO 8601 UTC."
        }
      },
      "description": "Present only when the mirror answered less than the requested window. Every count, share, and article in this response comes from answeredStart through answeredEnd; nothing outside it, or in a missing slot, was counted.",
      "additionalProperties": false
    },
    "histogram": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "bin",
          "count",
          "articles",
          "referenceCount"
        ],
        "properties": {
          "bin": {
            "type": "number",
            "description": "Tone bin integer (typically -30 to +30; 0 is neutral)."
          },
          "count": {
            "type": "number",
            "description": "Number of articles in this bin."
          },
          "articles": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "url",
                "title"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "description": "Article URL."
                },
                "title": {
                  "type": "string",
                  "description": "Article title."
                }
              },
              "description": "A representative article for this tone bin.",
              "additionalProperties": false
            },
            "description": "Representative articles in this tone bin — the first 3, or all of them for a bin named in bins."
          },
          "referenceCount": {
            "type": "number",
            "description": "How many representative articles GDELT returned for this bin; articles carries the first 3 unless the bin was named in bins."
          }
        },
        "description": "A single tone histogram bin with article count and representative articles.",
        "additionalProperties": false
      },
      "description": "The bins of this page, sorted from most negative to most positive — the whole histogram when it fits."
    },
    "limitClamp": {
      "type": "object",
      "required": [
        "parameter",
        "requested",
        "applied"
      ],
      "properties": {
        "applied": {
          "type": "number",
          "description": "The per-call cap the call ran with instead."
        },
        "parameter": {
          "enum": [
            "maxRecords",
            "limit"
          ],
          "type": "string",
          "description": "The count input that was clamped."
        },
        "requested": {
          "type": "number",
          "description": "The value the call asked for."
        }
      },
      "description": "Present only when the requested count exceeded the per-call cap: the call ran exactly as a call at the cap, and every count, notice, and continuation in this response reflects the applied value.",
      "additionalProperties": false
    },
    "nextOffset": {
      "type": "number",
      "description": "Offset of the next page, for the same inputs. Absent when this page reaches the last bin."
    },
    "totalCount": {
      "type": "number",
      "description": "Total number of articles across all histogram bins, not only this page."
    },
    "endDatetime": {
      "type": "string",
      "description": "Echoed end datetime when provided (YYYYMMDDHHMMSS)."
    },
    "staleResponse": {
      "type": "object",
      "required": [
        "fetchedAt",
        "ageSeconds",
        "reason"
      ],
      "properties": {
        "reason": {
          "enum": [
            "gdelt_rate_limited",
            "gdelt_unavailable",
            "gdelt_empty"
          ],
          "type": "string",
          "description": "Why the refetch was not used: GDELT rate-limited it, did not answer with data, or answered empty — which GDELT also does under load."
        },
        "fetchedAt": {
          "type": "string",
          "description": "ISO 8601 time GDELT returned the stored answer."
        },
        "ageSeconds": {
          "type": "number",
          "description": "Age of the stored answer when served, in whole seconds."
        }
      },
      "description": "Present only when the refetch of this exact request was refused, failed, or came back empty, and the response is GDELT's stored answer from fetchedAt instead. It holds nothing published after fetchedAt; a relative timespan covers the window ending at fetchedAt, not now. Absent on a live answer.",
      "additionalProperties": false
    },
    "startDatetime": {
      "type": "string",
      "description": "Echoed start datetime when provided (YYYYMMDDHHMMSS)."
    },
    "effectiveQuery": {
      "type": "string",
      "description": "Echoed query string for use in follow-up calls."
    }
  },
  "additionalProperties": false
}
gdelt_get_tone_distribution annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
gdelt_get_coverage_breakdown — Get GDELT Coverage Breakdown
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Break down news coverage volume over time by source language or source country, returning a multi-series time series (one series per language or country). Shows which countries or languages drove early vs. late coverage — useful for tracing how a story propagated geographically or across language communities. Returns the top 10 series ranked by the sum of their values and names every other series under otherSeriesLabels — pass any labels, ranked or not, as the series input to get only those series, complete. A response carries limit series (default 10, cap 75); when more remain it returns nextOffset — pass it back as offset with otherwise identical inputs for the next page. Values are normalized: each point is the topic's share of that source's media output, not an absolute article count, so values from different sources do not add up to a share. Small media markets with concentrated coverage therefore rank above large markets with diverse output — a high value means the topic dominated that source's coverage, not that it published the most articles. Use breakdownBy "country" with the signal-detection chain to map geographic attention, or "language" to detect non-English media surges.

gdelt_get_coverage_breakdown input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "query",
    "breakdownBy"
  ],
  "properties": {
    "limit": {
      "type": "number",
      "default": 10,
      "minimum": 1,
      "multipleOf": 1,
      "description": "Maximum series per page (default 10, cap 75). Larger counts clamp to 75 unless GDELT_CLAMP_LIMITS=false."
    },
    "query": {
      "type": "string",
      "minLength": 1,
      "description": "Search query using GDELT syntax. Same operators as gdelt_search_articles: phrases, boolean OR, sourcecountry:, sourcelang:, domain:, theme: (GKG theme identifiers come from gdelt_search_themes)."
    },
    "offset": {
      "type": "integer",
      "default": 0,
      "maximum": 9007199254740991,
      "minimum": 0,
      "description": "Zero-based series offset — into the ranked top 10, or into the series named in series. Pass nextOffset from the preceding response, with otherwise identical inputs, to get the next page."
    },
    "series": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Exact series labels to return instead of the ranked overview, e.g. [\"Portuguese Volume Intensity\", \"Vietnamese Volume Intensity\"]. Take them verbatim from otherSeriesLabels or topSeries[].label in a response, or from the label list an unknown_series error prints. Each one comes back complete under selectedSeries, in the order requested; a label that matches nothing is rejected rather than silently skipped. Omit to get the ranked overview."
    },
    "timespan": {
      "type": "string",
      "description": "Time window relative to now, minimum \"15min\"; other examples: \"24h\", \"7d\", \"1m\". Ignored when startDatetime/endDatetime are set. Maximum 3 months."
    },
    "smoothing": {
      "type": "integer",
      "maximum": 30,
      "minimum": 0,
      "description": "Trailing moving-average width in timesteps (0–30; 0 or 1 leaves values unsmoothed). Width N needs N source steps, omitting leading steps without a full window and potentially shifting peaks later."
    },
    "breakdownBy": {
      "enum": [
        "language",
        "country"
      ],
      "type": "string",
      "description": "Breakdown dimension: \"language\" for source language time series, \"country\" for source country time series."
    },
    "endDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "End datetime in GDELT format YYYYMMDDHHMMSS — exactly 14 digits, no separators (e.g. 20240131235959). Must pair with startDatetime; supplying only one of the two is rejected. The window may predate the last 3 months."
    },
    "startDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "Start datetime in GDELT format YYYYMMDDHHMMSS — exactly 14 digits, no separators (e.g. 20240101000000). Must pair with endDatetime; supplying only one of the two is rejected. The window may predate the last 3 months."
    }
  },
  "additionalProperties": false
}
gdelt_get_coverage_breakdown output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "effectiveQuery",
        "breakdownBy",
        "totalCount"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "unknown_series",
                "offset_out_of_range",
                "invalid_date_range",
                "invalid_query",
                "gdelt_rate_limited",
                "gdelt_unavailable"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `unknown_series`: A label passed in the series input matches no series in a non-empty breakdown. `offset_out_of_range`: The requested offset is at or beyond the last series of a non-empty overview (the top 10), or of the series named in series. `invalid_date_range`: Only one of startDatetime / endDatetime was supplied, one of them is not a real UTC calendar timestamp, or startDatetime is not earlier than endDatetime. `invalid_query`: GDELT rejected the query string as malformed — bad keyword length, unbalanced parentheses, or an illegal character. `gdelt_rate_limited`: GDELT rejected the request for its one-request-per-five-seconds limit, or too many requests were already queued for this one to start in time. `gdelt_unavailable`: GDELT DOC API is unreachable or temporarily returned no usable data. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "notice": {
      "type": "string",
      "description": "Guidance when the query matched no coverage in the window — how to broaden the query or extend the window — or, when this response is one page of several, which series it returned out of how many. When the server's local GKG mirror answered (source: gkg_mirror), why, how its figures differ from the DOC API's, and how many matching articles a country breakdown left out for having no known source country. Absent when the DOC API answered and every series fit in one response."
    },
    "source": {
      "enum": [
        "doc_api",
        "gkg_mirror"
      ],
      "type": "string",
      "description": "Where this answer came from: doc_api, the GDELT DOC API, or gkg_mirror, the server's local mirror of GDELT's Global Knowledge Graph, which answers when the DOC API refuses the request or returns nothing. Present on every answer while the server runs a mirror; absent otherwise."
    },
    "attempts": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "source",
          "outcome"
        ],
        "properties": {
          "detail": {
            "type": "string",
            "description": "Why, when the outcome has a reason: DOC's failure message or the mirror's."
          },
          "source": {
            "enum": [
              "doc_api",
              "gkg_mirror"
            ],
            "type": "string",
            "description": "The source tried."
          },
          "outcome": {
            "enum": [
              "answered",
              "empty",
              "rate_limited",
              "unavailable",
              "not_ready",
              "not_compiled",
              "outside_coverage",
              "store_error"
            ],
            "type": "string",
            "description": "What the source did: answered, empty (answered with no matches), rate_limited, or unavailable; or why the mirror could not answer: not_ready (no completed sync), not_compiled (the query or its timespan is in a form the mirror cannot evaluate), outside_coverage (the window lies outside the days it holds), store_error."
          }
        },
        "description": "One source's outcome for this call.",
        "additionalProperties": false
      },
      "description": "Each source tried for this call, in order. Present only when the DOC API did not answer with data and the mirror was consulted."
    },
    "coverage": {
      "type": "object",
      "required": [
        "requestedStart",
        "requestedEnd",
        "answeredStart",
        "answeredEnd",
        "missingSlots"
      ],
      "properties": {
        "answeredEnd": {
          "type": "string",
          "description": "End of the window the mirror answered, ISO 8601 UTC."
        },
        "missingSlots": {
          "type": "number",
          "description": "15-minute GKG slots inside the answered window that the mirror holds no data for."
        },
        "requestedEnd": {
          "type": "string",
          "description": "End of the requested window, ISO 8601 UTC."
        },
        "answeredStart": {
          "type": "string",
          "description": "Start of the window the mirror answered, ISO 8601 UTC."
        },
        "requestedStart": {
          "type": "string",
          "description": "Start of the requested window, ISO 8601 UTC."
        }
      },
      "description": "Present only when the mirror answered less than the requested window. Every count, share, and article in this response comes from answeredStart through answeredEnd; nothing outside it, or in a missing slot, was counted.",
      "additionalProperties": false
    },
    "topSeries": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "label",
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "date",
                "value"
              ],
              "properties": {
                "date": {
                  "type": "string",
                  "description": "Timestep in ISO 8601 format."
                },
                "value": {
                  "type": "number",
                  "description": "Normalized coverage volume at this timestep — the topic's share of this source's media output, not an absolute article count."
                }
              },
              "description": "A single data point for this series.",
              "additionalProperties": false
            },
            "description": "Time-ordered data points for this series."
          },
          "label": {
            "type": "string",
            "description": "Series label (language name or country name)."
          }
        },
        "description": "A single language or country coverage series.",
        "additionalProperties": false
      },
      "description": "The ranked overview: the top 10 series by the sum of their values, those of this page in rank order. Omitted when the series input selects series instead."
    },
    "limitClamp": {
      "type": "object",
      "required": [
        "parameter",
        "requested",
        "applied"
      ],
      "properties": {
        "applied": {
          "type": "number",
          "description": "The per-call cap the call ran with instead."
        },
        "parameter": {
          "enum": [
            "maxRecords",
            "limit"
          ],
          "type": "string",
          "description": "The count input that was clamped."
        },
        "requested": {
          "type": "number",
          "description": "The value the call asked for."
        }
      },
      "description": "Present only when the requested count exceeded the per-call cap: the call ran exactly as a call at the cap, and every count, notice, and continuation in this response reflects the applied value.",
      "additionalProperties": false
    },
    "nextOffset": {
      "type": "number",
      "description": "Offset of the next page, for the same inputs. Absent when this page reaches the last series."
    },
    "totalCount": {
      "type": "number",
      "description": "Total number of series GDELT returned, before ranking into the top 10 or paging."
    },
    "breakdownBy": {
      "enum": [
        "language",
        "country"
      ],
      "type": "string",
      "description": "Breakdown dimension used for this response."
    },
    "endDatetime": {
      "type": "string",
      "description": "Echoed end datetime when provided (YYYYMMDDHHMMSS)."
    },
    "staleResponse": {
      "type": "object",
      "required": [
        "fetchedAt",
        "ageSeconds",
        "reason"
      ],
      "properties": {
        "reason": {
          "enum": [
            "gdelt_rate_limited",
            "gdelt_unavailable",
            "gdelt_empty"
          ],
          "type": "string",
          "description": "Why the refetch was not used: GDELT rate-limited it, did not answer with data, or answered empty — which GDELT also does under load."
        },
        "fetchedAt": {
          "type": "string",
          "description": "ISO 8601 time GDELT returned the stored answer."
        },
        "ageSeconds": {
          "type": "number",
          "description": "Age of the stored answer when served, in whole seconds."
        }
      },
      "description": "Present only when the refetch of this exact request was refused, failed, or came back empty, and the response is GDELT's stored answer from fetchedAt instead. It holds nothing published after fetchedAt; a relative timespan covers the window ending at fetchedAt, not now. Absent on a live answer.",
      "additionalProperties": false
    },
    "startDatetime": {
      "type": "string",
      "description": "Echoed start datetime when provided (YYYYMMDDHHMMSS)."
    },
    "dateResolution": {
      "enum": [
        "15min",
        "hour",
        "day"
      ],
      "type": "string",
      "description": "Temporal resolution of data points — 15min, hour, or day — inferred from the spacing of the returned timesteps. Omitted when fewer than two distinct timesteps came back."
    },
    "effectiveQuery": {
      "type": "string",
      "description": "Echoed query string for use in follow-up calls."
    },
    "selectedSeries": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "label",
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "date",
                "value"
              ],
              "properties": {
                "date": {
                  "type": "string",
                  "description": "Timestep in ISO 8601 format."
                },
                "value": {
                  "type": "number",
                  "description": "Normalized coverage volume at this timestep — the topic's share of this source's media output, not an absolute article count."
                }
              },
              "description": "A single data point for this series.",
              "additionalProperties": false
            },
            "description": "Time-ordered data points for this series."
          },
          "label": {
            "type": "string",
            "description": "Series label (language name or country name)."
          }
        },
        "description": "A single language or country coverage series.",
        "additionalProperties": false
      },
      "description": "Complete, untruncated time series for the labels requested via the series input — those of this page, in the order requested. Omitted when series was not supplied."
    },
    "otherSeriesLabels": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Label of every series beyond the top 10, ranked by the sum of its values, on every overview page. Pass any of them to the series input to retrieve that series' complete data. Omitted when all series fit in the top 10, or when the series input selects series instead."
    }
  },
  "additionalProperties": false
}
gdelt_get_coverage_breakdown annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
gdelt_search_themes — Search GDELT GKG Themes
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Find GDELT Global Knowledge Graph (GKG) theme identifiers for the theme: operator that gdelt_search_articles, gdelt_get_coverage_timeline, gdelt_get_tone_distribution, and gdelt_get_coverage_breakdown accept in query. Searches the identifiers in the GDELT GKG theme lookup, which carries no labels or descriptions: every query word must begin one of the _-separated parts of an identifier or run across consecutive parts, or all the words joined must, so "drought" finds NATURAL_DISASTER_DROUGHT, "cyberattack" finds CYBER_ATTACK, "plant disease" finds TAX_PLANTDISEASE, and "wb water" narrows to World Bank water themes. There is no stemming or synonym matching — "displacement" does not reach DISPLACED — except one fallback: when nothing matches, the search retries once with a trailing s dropped from each word of four or more letters, and says so. Matches rank an exact identifier first, then by the count the lookup lists — a static prevalence figure, not a live article total — and each carries a paste-ready operator such as theme:TAX_DISEASE_OUTBREAK. Page with offset and limit (up to 100 matches per page; a larger limit runs at 100).

gdelt_search_themes input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "query"
  ],
  "properties": {
    "limit": {
      "type": "number",
      "default": 25,
      "minimum": 1,
      "multipleOf": 1,
      "description": "Maximum matches returned in this response. Values above 100 run at 100 with a limitClamp disclosure when clamping is enabled."
    },
    "query": {
      "type": "string",
      "description": "Words to find in theme identifiers (e.g. \"drought\", \"cyber attack\", \"refugee\"), a family prefix with a word (\"wb water\", \"crisislex\"), or a whole identifier to confirm it is listed (\"TAX_DISEASE_OUTBREAK\"). Case-insensitive; a leading theme: is ignored; every word must match, or all the words joined must (\"plant disease\" matches TAX_PLANTDISEASE). Must contain at least one letter or digit."
    },
    "offset": {
      "type": "integer",
      "default": 0,
      "maximum": 9007199254740991,
      "minimum": 0,
      "description": "Zero-based offset into the ranked matches. Use nextOffset from the preceding response with the same query to retrieve the next page."
    }
  },
  "additionalProperties": false
}
gdelt_search_themes output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "matches",
        "totalMatches",
        "offset",
        "limit",
        "effectiveQuery",
        "totalCount"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "invalid_query",
                "offset_out_of_range",
                "gdelt_unavailable"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `invalid_query`: The query has no letter or digit to match — blank, whitespace, or only punctuation such as \"___\". `offset_out_of_range`: The requested offset is at or beyond the end of a non-empty match list. `gdelt_unavailable`: The GDELT GKG theme lookup could not be downloaded, or came back empty or not as THEME<TAB>count lines. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "limit": {
      "type": "number",
      "description": "Maximum matches this page holds — the requested limit, or 100 when a larger one was clamped."
    },
    "notice": {
      "type": "string",
      "description": "Search outcome: that the plural fallback supplied the matches and which words it tried, or, when nothing matched, how to retry. Absent when the query as given matched."
    },
    "offset": {
      "type": "number",
      "description": "Zero-based offset of this page."
    },
    "matches": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "theme",
          "count",
          "operator"
        ],
        "properties": {
          "count": {
            "type": "number",
            "description": "Count the GDELT theme lookup lists for this theme — a static prevalence figure, not a live article total."
          },
          "theme": {
            "type": "string",
            "description": "GKG theme identifier (e.g. \"NATURAL_DISASTER_DROUGHT\")."
          },
          "operator": {
            "type": "string",
            "description": "Paste-ready query operator for the DOC tools (e.g. \"theme:NATURAL_DISASTER_DROUGHT\")."
          }
        },
        "description": "A matching GKG theme.",
        "additionalProperties": false
      },
      "description": "Matches on this page: an exact identifier match first, then by count descending, then by identifier."
    },
    "limitClamp": {
      "type": "object",
      "required": [
        "parameter",
        "requested",
        "applied"
      ],
      "properties": {
        "applied": {
          "type": "number",
          "description": "The per-call cap the call ran with instead."
        },
        "parameter": {
          "enum": [
            "maxRecords",
            "limit"
          ],
          "type": "string",
          "description": "The count input that was clamped."
        },
        "requested": {
          "type": "number",
          "description": "The value the call asked for."
        }
      },
      "description": "Present only when the requested count exceeded the per-call cap: the call ran exactly as a call at the cap, and every count, notice, and continuation in this response reflects the applied value.",
      "additionalProperties": false
    },
    "nextOffset": {
      "type": "number",
      "description": "Offset for the next page with the same query. Absent when this is the final page."
    },
    "totalCount": {
      "type": "number",
      "description": "Total themes matching the query — the same figure as totalMatches."
    },
    "totalMatches": {
      "type": "number",
      "description": "Total themes matching the query, across all pages."
    },
    "effectiveQuery": {
      "type": "string",
      "description": "Echoed query string for use in follow-up calls."
    }
  },
  "additionalProperties": false
}
gdelt_search_themes annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
gdelt_search_tv — Search GDELT TV News
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Search television news closed captions for spoken mentions of a query. Returns a bounded, paged per-station time series showing airtime devoted to the topic — 500 points by default, up to 20,000 per page. Each series carries GDELT's display name for the station and, when that name resolves to one, the station ID gdelt_get_tv_clips takes as stations. Use stations to select station IDs (e.g. ["CNN", "FOXNEWS", "MSNBC"]), or select with station:, network:, or quoted market: operators in query. TV query also supports in-query operators: station:CNN, network:CBS, market:"National", show:"Anderson Cooper 360", context:"vaccine". Archive coverage varies by station; use gdelt_list_tv_stations for station IDs, network and market values, and monitoring date ranges.

gdelt_search_tv input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "query"
  ],
  "properties": {
    "limit": {
      "type": "number",
      "default": 500,
      "minimum": 1,
      "multipleOf": 1,
      "description": "Maximum timeline points returned per page (default 500, cap 20,000). Larger counts clamp with limitClamp; strict deployments reject them."
    },
    "query": {
      "type": "string",
      "minLength": 1,
      "description": "Search query for TV transcript content. Supports TV operators: station:CNN, network:CBS, market:\"National\", show:\"Anderson Cooper\", context:\"vaccine\". Boolean OR and phrase operators also work."
    },
    "offset": {
      "type": "integer",
      "default": 0,
      "maximum": 9007199254740991,
      "minimum": 0,
      "description": "Zero-based point offset into the deterministic date-then-station-name ordering. Use nextOffset from the preceding response with the same query inputs to retrieve the next page."
    },
    "dateres": {
      "enum": [
        "hour",
        "day",
        "week",
        "month",
        "year"
      ],
      "type": "string",
      "description": "Optional GDELT aggregation resolution. Omit to let GDELT choose from the query window; the effective recognized or inferred resolution is returned as dateResolution."
    },
    "combined": {
      "type": "boolean",
      "default": false,
      "description": "Pool selected stations into one Combined timeline. Normalized values divide pooled matching clips by pooled monitored clips; false keeps separate station series."
    },
    "stations": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Station IDs to filter to (e.g. [\"CNN\", \"FOXNEWS\", \"MSNBC\"]). Every supplied ID is forwarded. Alternatively use station:, network:, or quoted market: selectors in query; a selector is required. Obtain IDs, network and market values, and per-station archive ranges from gdelt_list_tv_stations."
    },
    "timespan": {
      "type": "string",
      "description": "Time window, e.g. \"1m\", \"6m\", \"1y\". Ignored when startDatetime/endDatetime are set. Check station monitoring dates with gdelt_list_tv_stations."
    },
    "normalize": {
      "type": "boolean",
      "default": true,
      "description": "When true (default), values are normalized as % of total airtime, enabling cross-station comparison. When false, returns raw matching 15-second clip counts."
    },
    "smoothing": {
      "type": "integer",
      "maximum": 30,
      "minimum": 0,
      "description": "Trailing moving-average width in timesteps, 0–30 (0 or 1 = none). Width N needs N source steps; leading steps cannot produce averages and peaks may appear later."
    },
    "endDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "End datetime in GDELT format YYYYMMDDHHMMSS — exactly 14 digits, no separators (e.g. 20200131235959). Must pair with startDatetime; supplying only one of the two is rejected."
    },
    "startDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "Start datetime in GDELT format YYYYMMDDHHMMSS — exactly 14 digits, no separators (e.g. 20200101000000). Must pair with endDatetime; supplying only one of the two is rejected."
    }
  },
  "additionalProperties": false
}
gdelt_search_tv output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "combined",
        "series",
        "normalized",
        "totalPoints",
        "offset",
        "limit",
        "effectiveQuery",
        "totalCount"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "invalid_date_range",
                "offset_out_of_range",
                "invalid_query",
                "gdelt_rate_limited",
                "gdelt_unavailable"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `invalid_date_range`: Only one of startDatetime / endDatetime was supplied, one of them is not a real UTC calendar timestamp, or startDatetime is not earlier than endDatetime. `offset_out_of_range`: The requested point offset is at or beyond the end of a non-empty timeline. `invalid_query`: GDELT rejected the query — no station was selected, or the query string is malformed. `gdelt_rate_limited`: GDELT rejected the request for its one-request-per-five-seconds limit, or too many requests were already queued for this one to start in time. `gdelt_unavailable`: GDELT TV API is unreachable or temporarily returned no usable data. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "limit": {
      "type": "number",
      "description": "Maximum points this page holds — the requested limit, or 20,000 when a larger one was clamped."
    },
    "notice": {
      "type": "string",
      "description": "Guidance when the query matched no TV coverage — the resolved timespan window, the October 2024 archive cutoff, and how to check station coverage. When a returned series has no station ID, why: GDELT returned it without a station label, or its station catalog did not load or has no entry for the named label — with how to look the ID up. Absent when coverage was returned and every series carries its station ID."
    },
    "offset": {
      "type": "number",
      "description": "Zero-based offset of this point page."
    },
    "series": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "stationName",
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "date",
                "value"
              ],
              "properties": {
                "date": {
                  "type": "string",
                  "description": "Timestep in ISO 8601 format."
                },
                "value": {
                  "type": "number",
                  "description": "Coverage value (normalized % or raw matching 15-second clip count)."
                }
              },
              "description": "A single coverage data point.",
              "additionalProperties": false
            },
            "description": "Time-ordered coverage data for this station."
          },
          "station": {
            "type": "string",
            "description": "Station ID — the value the stations input and the station: operator take (e.g. \"FOXNEWS\"). Absent when GDELT's label for the station could not be resolved to an ID; notice says why."
          },
          "stationName": {
            "type": "string",
            "description": "GDELT's display label for the station (e.g. \"FOX News\"). Empty when GDELT returned the series without one; notice says so."
          }
        },
        "description": "Coverage time series for a single station.",
        "additionalProperties": false
      },
      "description": "Station series represented in this point page."
    },
    "combined": {
      "type": "boolean",
      "description": "True for one pooled Combined timeline; false for separate station series."
    },
    "timeRange": {
      "type": "object",
      "required": [
        "start",
        "end"
      ],
      "properties": {
        "end": {
          "type": "string",
          "description": "Latest date in the returned data."
        },
        "start": {
          "type": "string",
          "description": "Earliest date in the returned data."
        }
      },
      "description": "Date range spanned by this returned point page. Omitted when the page is empty.",
      "additionalProperties": false
    },
    "limitClamp": {
      "type": "object",
      "required": [
        "parameter",
        "requested",
        "applied"
      ],
      "properties": {
        "applied": {
          "type": "number",
          "description": "The per-call cap the call ran with instead."
        },
        "parameter": {
          "enum": [
            "maxRecords",
            "limit"
          ],
          "type": "string",
          "description": "The count input that was clamped."
        },
        "requested": {
          "type": "number",
          "description": "The value the call asked for."
        }
      },
      "description": "Present only when the requested count exceeded the per-call cap: the call ran exactly as a call at the cap, and every count, notice, and continuation in this response reflects the applied value.",
      "additionalProperties": false
    },
    "nextOffset": {
      "type": "number",
      "description": "Offset for the next page using the same query inputs. Absent when this is the final page."
    },
    "normalized": {
      "type": "boolean",
      "description": "True when values are normalized coverage percentages."
    },
    "totalCount": {
      "type": "number",
      "description": "Number of station series returned."
    },
    "totalPoints": {
      "type": "number",
      "description": "Total points available across all matched station series before pagination."
    },
    "staleResponse": {
      "type": "object",
      "required": [
        "fetchedAt",
        "ageSeconds",
        "reason"
      ],
      "properties": {
        "reason": {
          "enum": [
            "gdelt_rate_limited",
            "gdelt_unavailable",
            "gdelt_empty"
          ],
          "type": "string",
          "description": "Why the refetch was not used: GDELT rate-limited it, did not answer with data, or answered empty — which GDELT also does under load."
        },
        "fetchedAt": {
          "type": "string",
          "description": "ISO 8601 time GDELT returned the stored answer."
        },
        "ageSeconds": {
          "type": "number",
          "description": "Age of the stored answer when served, in whole seconds."
        }
      },
      "description": "Present only when the refetch of this exact request was refused, failed, or came back empty, and the response is GDELT's stored answer from fetchedAt instead. It holds nothing published after fetchedAt; a relative timespan covers the window ending at fetchedAt, not now. Absent on a live answer.",
      "additionalProperties": false
    },
    "dateResolution": {
      "enum": [
        "hour",
        "day",
        "week",
        "month",
        "year"
      ],
      "type": "string",
      "description": "Temporal resolution of data points — as GDELT reported it, as requested via dateres, or inferred from the returned intervals. Omitted when none of those can establish it."
    },
    "effectiveQuery": {
      "type": "string",
      "description": "Echoed query string for use in follow-up calls."
    }
  },
  "additionalProperties": false
}
gdelt_search_tv annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
gdelt_get_tv_breakdown — Get GDELT TV Breakdown
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Rank TV stations or shows mentioning a query. Station values are percentages of each station’s monitored airtime, or raw matching 15-second clip counts with normalize=false. Show values always represent percentages of matching clips, even with normalize=false. Labels are preserved exactly; ellipsized show labels may not work as exact show: selectors. Returns 25 rows by default, up to 10,000 per page. Archive coverage varies by station; use gdelt_list_tv_stations for station IDs, network and market selectors, and monitoring date ranges.

gdelt_get_tv_breakdown input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "query",
    "breakdownBy"
  ],
  "properties": {
    "limit": {
      "type": "number",
      "default": 25,
      "minimum": 1,
      "multipleOf": 1,
      "description": "Maximum ranking rows per page (default 25, cap 10,000). Larger counts clamp with limitClamp; strict deployments reject them."
    },
    "query": {
      "type": "string",
      "minLength": 1,
      "description": "TV transcript query. Supports phrases, Boolean OR, station:CNN, network:CBS, market:\"National\", show:\"Bloomberg Best\", and context:\"vaccine\"."
    },
    "offset": {
      "type": "integer",
      "default": 0,
      "maximum": 9007199254740991,
      "minimum": 0,
      "description": "Zero-based row offset after descending-value and exact-label sorting. Use nextOffset with the same query inputs for the next page."
    },
    "stations": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Station IDs to select; every supplied ID is forwarded. Alternatively select station:, network:, or quoted market: in query. A selector is required; obtain values from gdelt_list_tv_stations."
    },
    "timespan": {
      "type": "string",
      "description": "Relative time window, such as 1m or 6m. Ignored when both explicit datetimes are supplied. Check per-station archive coverage before selecting a window."
    },
    "normalize": {
      "type": "boolean",
      "default": true,
      "description": "Station rankings: true returns station-airtime percentages; false returns matching 15-second clip counts. Show rankings always return matching-clip percentages."
    },
    "breakdownBy": {
      "enum": [
        "station",
        "show"
      ],
      "type": "string",
      "description": "Rank stations by their airtime share or matching clip count, or shows by percentage of matching clips."
    },
    "endDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "UTC end in YYYYMMDDHHMMSS format. Must pair with an earlier startDatetime."
    },
    "startDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "UTC start in YYYYMMDDHHMMSS format. Must pair with a later endDatetime."
    }
  },
  "additionalProperties": false
}
gdelt_get_tv_breakdown output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "rows",
        "valueUnit",
        "totalRows",
        "offset",
        "limit",
        "truncated",
        "effectiveQuery"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "rows": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "label",
          "value"
        ],
        "properties": {
          "label": {
            "type": "string",
            "description": "Exact provider station or show label, including any ellipsis."
          },
          "value": {
            "type": "number",
            "description": "Ranking value in valueUnit; no rescaling is applied."
          },
          "station": {
            "type": "string",
            "description": "Catalog station ID for a resolved station row; absent for shows or unresolved labels."
          }
        },
        "description": "A station or show ranking row.",
        "additionalProperties": false
      },
      "description": "Rows sorted by descending value, breaking ties by exact label, from the requested page."
    },
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "invalid_date_range",
                "offset_out_of_range",
                "invalid_query",
                "gdelt_rate_limited",
                "gdelt_unavailable"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `invalid_date_range`: Only one explicit datetime was supplied, a datetime is not a real UTC timestamp, or startDatetime is not earlier than endDatetime. `offset_out_of_range`: The requested row offset is at or beyond the end of a non-empty ranking. `invalid_query`: GDELT rejected the query or the TV timespan is malformed. `gdelt_rate_limited`: GDELT rejected its request-spacing limit, or the request queue could not start this call in time. `gdelt_unavailable`: GDELT TV API is unreachable or temporarily returned no usable data. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "limit": {
      "type": "number",
      "description": "Applied maximum rows on this page."
    },
    "notice": {
      "type": "string",
      "description": "Empty-result guidance, show percentage and selector limitations, or station catalog resolution limitations."
    },
    "offset": {
      "type": "number",
      "description": "Zero-based offset of this ranking page."
    },
    "totalRows": {
      "type": "number",
      "description": "Full ranking row count before pagination."
    },
    "truncated": {
      "type": "boolean",
      "description": "True when additional rows remain after this page."
    },
    "valueUnit": {
      "enum": [
        "percent_station_airtime",
        "percent_matching_clips",
        "matching_clips"
      ],
      "type": "string",
      "description": "Station-airtime percentage, matching-clip percentage for shows, or raw matching 15-second clip count for stations."
    },
    "limitClamp": {
      "type": "object",
      "required": [
        "parameter",
        "requested",
        "applied"
      ],
      "properties": {
        "applied": {
          "type": "number",
          "description": "The per-call cap the call ran with instead."
        },
        "parameter": {
          "enum": [
            "maxRecords",
            "limit"
          ],
          "type": "string",
          "description": "The count input that was clamped."
        },
        "requested": {
          "type": "number",
          "description": "The value the call asked for."
        }
      },
      "description": "Present only when the requested count exceeded the per-call cap: the call ran exactly as a call at the cap, and every count, notice, and continuation in this response reflects the applied value.",
      "additionalProperties": false
    },
    "nextOffset": {
      "type": "number",
      "description": "Offset of the next page; absent when no rows remain."
    },
    "staleResponse": {
      "type": "object",
      "required": [
        "fetchedAt",
        "ageSeconds",
        "reason"
      ],
      "properties": {
        "reason": {
          "enum": [
            "gdelt_rate_limited",
            "gdelt_unavailable",
            "gdelt_empty"
          ],
          "type": "string",
          "description": "Why the refetch was not used: GDELT rate-limited it, did not answer with data, or answered empty — which GDELT also does under load."
        },
        "fetchedAt": {
          "type": "string",
          "description": "ISO 8601 time GDELT returned the stored answer."
        },
        "ageSeconds": {
          "type": "number",
          "description": "Age of the stored answer when served, in whole seconds."
        }
      },
      "description": "Present only when the refetch of this exact request was refused, failed, or came back empty, and the response is GDELT's stored answer from fetchedAt instead. It holds nothing published after fetchedAt; a relative timespan covers the window ending at fetchedAt, not now. Absent on a live answer.",
      "additionalProperties": false
    },
    "effectiveQuery": {
      "type": "string",
      "description": "Echoed query for follow-up calls."
    }
  },
  "additionalProperties": false
}
gdelt_get_tv_breakdown annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
gdelt_get_tv_clips — Get GDELT TV Clips
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Retrieve the top matching TV news clips for a query from the Internet Archive's Television News Archive: returns every fetched in-window clip, up to 3,000. Each clip includes show name, the station's display name — with its station ID when that name resolves to one — air timestamp, a 15-second transcript excerpt, and a direct link to view the full one-minute clip. Use after gdelt_search_tv to read the actual transcript content driving a coverage spike — pass a series' station value as stations here. GDELT answers TV windows in whole clock hours; clips it returns from outside an explicit startDatetime/endDatetime window are dropped. 3,000 is a hard per-call ceiling and GDELT offers no cursor: when a query fills it, re-query narrower startDatetime/endDatetime windows — the response hands back the exact windows to use. Archive coverage varies by station; use gdelt_list_tv_stations for station IDs and monitoring date ranges.

gdelt_get_tv_clips input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "query"
  ],
  "properties": {
    "sort": {
      "enum": [
        "relevance",
        "dateDesc",
        "dateAsc"
      ],
      "type": "string",
      "default": "relevance",
      "description": "Sort order: relevance (default), dateDesc (newest first), dateAsc (oldest first)."
    },
    "query": {
      "type": "string",
      "minLength": 1,
      "description": "Search query for TV transcript content. Same TV operators as gdelt_search_tv: station:CNN, network:CBS, market:\"National\", show:\"Anderson Cooper\", context:\"vaccine\"."
    },
    "stations": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Station IDs to filter to (e.g. [\"CNN\", \"FOXNEWS\"]). Alternatively use station:, network:, or quoted market: selectors in query. A selector is required; use gdelt_list_tv_stations for station IDs, networks, markets, and monitoring dates."
    },
    "timespan": {
      "type": "string",
      "description": "Time window, e.g. \"1m\", \"6m\". Ignored when startDatetime/endDatetime are set. TV coverage varies by station; check monitoring dates with gdelt_list_tv_stations."
    },
    "maxRecords": {
      "type": "number",
      "default": 50,
      "minimum": 1,
      "multipleOf": 1,
      "description": "Maximum number of clips to fetch. Defaults to 50; values above 3000 run at 3000 with a limitClamp disclosure unless clamping is disabled. Every fetched in-window record is returned. 3000 is GDELT's hard per-call ceiling, with no cursor; split a query that fills it into narrower startDatetime/endDatetime windows."
    },
    "endDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "End datetime in GDELT format YYYYMMDDHHMMSS — exactly 14 digits, no separators (e.g. 20200131235959). Must pair with startDatetime; supplying only one of the two is rejected."
    },
    "startDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "Start datetime in GDELT format YYYYMMDDHHMMSS — exactly 14 digits, no separators (e.g. 20200101000000). Must pair with endDatetime; supplying only one of the two is rejected."
    }
  },
  "additionalProperties": false
}
gdelt_get_tv_clips output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "clips",
        "effectiveQuery",
        "totalCount"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "clips": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "show",
          "stationName",
          "date",
          "snippet",
          "archiveUrl"
        ],
        "properties": {
          "date": {
            "type": "string",
            "description": "Air datetime in ISO 8601 format."
          },
          "show": {
            "type": "string",
            "description": "Show name (e.g. \"Anderson Cooper 360\")."
          },
          "snippet": {
            "type": "string",
            "description": "15-second transcript excerpt surrounding the match."
          },
          "station": {
            "type": "string",
            "description": "Station ID — the value the stations input and the station: operator take (e.g. \"FOXNEWS\"). Absent when GDELT's label for the station could not be resolved to an ID; notice says why."
          },
          "thumbnail": {
            "type": "string",
            "description": "Clip thumbnail URL when provided by the archive."
          },
          "archiveUrl": {
            "type": "string",
            "description": "Internet Archive URL to view the full 1-minute clip."
          },
          "stationName": {
            "type": "string",
            "description": "GDELT's display label for the station (e.g. \"FOX News\"). Empty when GDELT returned the clip without one; notice says so."
          }
        },
        "description": "A single TV news clip with transcript excerpt and archive link.",
        "additionalProperties": false
      },
      "description": "Matching TV clips sorted per the sort parameter."
    },
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "invalid_date_range",
                "invalid_query",
                "gdelt_rate_limited",
                "gdelt_unavailable"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `invalid_date_range`: Only one of startDatetime / endDatetime was supplied, one of them is not a real UTC calendar timestamp, or startDatetime is not earlier than endDatetime. `invalid_query`: GDELT rejected the query — no station was selected, or the query string is malformed. `gdelt_rate_limited`: GDELT rejected the request for its one-request-per-five-seconds limit, or too many requests were already queued for this one to start in time. `gdelt_unavailable`: GDELT TV API is unreachable or temporarily returned no usable data. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "notice": {
      "type": "string",
      "description": "Guidance on an incomplete or empty result. When no clips matched, the resolved timespan window and how to check station monitoring dates and choose an explicit window. When GDELT returned clips aired outside the requested window, how many were dropped. When the maxRecords cap was reached, raise maxRecords below the 3000 ceiling or narrow the date window at it. When a returned clip has no station ID, why: GDELT returned it without a station label, or its station catalog did not load or has no entry for the named label — with how to look the ID up. Absent when a non-empty result set is below the cap, no clip was dropped as out of window, and every clip carries its station ID."
    },
    "limitClamp": {
      "type": "object",
      "required": [
        "parameter",
        "requested",
        "applied"
      ],
      "properties": {
        "applied": {
          "type": "number",
          "description": "The per-call cap the call ran with instead."
        },
        "parameter": {
          "enum": [
            "maxRecords",
            "limit"
          ],
          "type": "string",
          "description": "The count input that was clamped."
        },
        "requested": {
          "type": "number",
          "description": "The value the call asked for."
        }
      },
      "description": "Present only when the requested count exceeded the per-call cap: the call ran exactly as a call at the cap, and every count, notice, and continuation in this response reflects the applied value.",
      "additionalProperties": false
    },
    "totalCount": {
      "type": "number",
      "description": "Number of clips returned."
    },
    "staleResponse": {
      "type": "object",
      "required": [
        "fetchedAt",
        "ageSeconds",
        "reason"
      ],
      "properties": {
        "reason": {
          "enum": [
            "gdelt_rate_limited",
            "gdelt_unavailable",
            "gdelt_empty"
          ],
          "type": "string",
          "description": "Why the refetch was not used: GDELT rate-limited it, did not answer with data, or answered empty — which GDELT also does under load."
        },
        "fetchedAt": {
          "type": "string",
          "description": "ISO 8601 time GDELT returned the stored answer."
        },
        "ageSeconds": {
          "type": "number",
          "description": "Age of the stored answer when served, in whole seconds."
        }
      },
      "description": "Present only when the refetch of this exact request was refused, failed, or came back empty, and the response is GDELT's stored answer from fetchedAt instead. It holds nothing published after fetchedAt; a relative timespan covers the window ending at fetchedAt, not now. Absent on a live answer.",
      "additionalProperties": false
    },
    "effectiveQuery": {
      "type": "string",
      "description": "Echoed query string for use in follow-up calls."
    },
    "continuationWindows": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "startDatetime",
          "endDatetime"
        ],
        "properties": {
          "endDatetime": {
            "type": "string",
            "description": "End of this window in GDELT format YYYYMMDDHHMMSS."
          },
          "startDatetime": {
            "type": "string",
            "description": "Start of this window in GDELT format YYYYMMDDHHMMSS."
          }
        },
        "description": "One window to re-query with the same query string.",
        "additionalProperties": false
      },
      "description": "Windows to re-run this query against when maxRecords reaches its 3000 ceiling: the queried window split in two on a clock hour, with no shared second. Absent when no window is known or narrowing cannot reach further clips."
    }
  },
  "additionalProperties": false
}
gdelt_get_tv_clips annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
gdelt_get_tv_context — Get GDELT TV Context
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Get the top co-occurring words and phrases from TV news clips matching a query — the vocabulary framing a topic on television. Returns the most frequent non-stopword terms with relative frequency scores (0–100, where 100 = the query term itself). Terms and scores come from GDELT's relevance-ranked sample of matching clips, documented as the 200 most relevant, not all matching coverage — compare windows or stations with a separate, narrower call for each. Use to understand narrative framing, identify related concepts mentioned alongside a topic, or generate follow-up search terms. Returns 25 terms by default, with count pages up to 25,000 terms. Archive coverage varies by station; check gdelt_list_tv_stations for each station’s monitoring date range.

gdelt_get_tv_context input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "query"
  ],
  "properties": {
    "limit": {
      "type": "number",
      "default": 25,
      "minimum": 1,
      "multipleOf": 1,
      "description": "Maximum score-sorted terms returned per page (default 25, cap 25,000). Larger counts clamp with limitClamp; strict deployments reject them."
    },
    "query": {
      "type": "string",
      "minLength": 1,
      "description": "Search query for TV transcript content. Same TV operators as gdelt_search_tv: station:CNN, network:CBS, market:\"National\", show:\"Anderson Cooper\", context:\"vaccine\"."
    },
    "offset": {
      "type": "integer",
      "default": 0,
      "maximum": 9007199254740991,
      "minimum": 0,
      "description": "Zero-based term offset in descending score order. Use nextOffset with the same query inputs for the next page."
    },
    "stations": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Station IDs to filter to (e.g. [\"CNN\", \"FOXNEWS\"]). Alternatively use station:, network:, or quoted market: selectors in query; a selector is required. Obtain IDs, network and market values, and per-station archive ranges from gdelt_list_tv_stations."
    },
    "timespan": {
      "type": "string",
      "description": "Time window, e.g. \"1m\", \"6m\". Ignored when startDatetime/endDatetime are set. Check station monitoring dates with gdelt_list_tv_stations."
    },
    "endDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "End datetime in GDELT format YYYYMMDDHHMMSS — exactly 14 digits, no separators (e.g. 20200131235959). Must pair with startDatetime; supplying only one of the two is rejected."
    },
    "startDatetime": {
      "type": "string",
      "pattern": "^\\d{14}$",
      "description": "Start datetime in GDELT format YYYYMMDDHHMMSS — exactly 14 digits, no separators (e.g. 20200101000000). Must pair with endDatetime; supplying only one of the two is rejected. Check station monitoring dates with gdelt_list_tv_stations."
    }
  },
  "additionalProperties": false
}
gdelt_get_tv_context output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "truncated",
        "totalTerms",
        "offset",
        "words",
        "effectiveQuery"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "offset_out_of_range",
                "invalid_date_range",
                "invalid_query",
                "gdelt_rate_limited",
                "gdelt_unavailable"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `offset_out_of_range`: The requested term offset is at or beyond the end of a non-empty result. `invalid_date_range`: Only one of startDatetime / endDatetime was supplied, one of them is not a real UTC calendar timestamp, or startDatetime is not earlier than endDatetime. `invalid_query`: GDELT rejected the query — no station was selected, or the query string is malformed. `gdelt_rate_limited`: GDELT rejected the request for its one-request-per-five-seconds limit, or too many requests were already queued for this one to start in time. `gdelt_unavailable`: GDELT TV API is unreachable or temporarily returned no usable data. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "words": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "label",
          "score"
        ],
        "properties": {
          "label": {
            "type": "string",
            "description": "Co-occurring word or phrase."
          },
          "score": {
            "type": "number",
            "description": "Relative frequency score (0–100). The query term itself scores 100; other terms are proportional to their co-occurrence frequency within GDELT's relevance-ranked sample of matching clips, documented as the 200 most relevant, not all matching coverage."
          }
        },
        "description": "A co-occurring term with its relative frequency score.",
        "additionalProperties": false
      },
      "description": "Co-occurring terms from GDELT's relevance-ranked sample of matching clips, documented as the 200 most relevant, not all matching coverage, sorted by score descending."
    },
    "notice": {
      "type": "string",
      "description": "On every non-empty result, that terms and scores come from GDELT's relevance-ranked sample of matching clips, documented as the 200 most relevant, not all matching coverage — compare windows or stations with a separate, narrower call for each. When no clips matched, so there is no vocabulary to report, the resolved timespan window and how to broaden the query or check station monitoring dates."
    },
    "offset": {
      "type": "number",
      "description": "Zero-based offset of this term page."
    },
    "truncated": {
      "type": "boolean",
      "description": "True when more terms remain after this page; use nextOffset to retrieve them."
    },
    "limitClamp": {
      "type": "object",
      "required": [
        "parameter",
        "requested",
        "applied"
      ],
      "properties": {
        "applied": {
          "type": "number",
          "description": "The per-call cap the call ran with instead."
        },
        "parameter": {
          "enum": [
            "maxRecords",
            "limit"
          ],
          "type": "string",
          "description": "The count input that was clamped."
        },
        "requested": {
          "type": "number",
          "description": "The value the call asked for."
        }
      },
      "description": "Present only when the requested count exceeded the per-call cap: the call ran exactly as a call at the cap, and every count, notice, and continuation in this response reflects the applied value.",
      "additionalProperties": false
    },
    "nextOffset": {
      "type": "number",
      "description": "Offset of the next term page; absent on the final page."
    },
    "totalTerms": {
      "type": "number",
      "description": "Total co-occurring terms before pagination; never a clip count."
    },
    "staleResponse": {
      "type": "object",
      "required": [
        "fetchedAt",
        "ageSeconds",
        "reason"
      ],
      "properties": {
        "reason": {
          "enum": [
            "gdelt_rate_limited",
            "gdelt_unavailable",
            "gdelt_empty"
          ],
          "type": "string",
          "description": "Why the refetch was not used: GDELT rate-limited it, did not answer with data, or answered empty — which GDELT also does under load."
        },
        "fetchedAt": {
          "type": "string",
          "description": "ISO 8601 time GDELT returned the stored answer."
        },
        "ageSeconds": {
          "type": "number",
          "description": "Age of the stored answer when served, in whole seconds."
        }
      },
      "description": "Present only when the refetch of this exact request was refused, failed, or came back empty, and the response is GDELT's stored answer from fetchedAt instead. It holds nothing published after fetchedAt; a relative timespan covers the window ending at fetchedAt, not now. Absent on a live answer.",
      "additionalProperties": false
    },
    "effectiveQuery": {
      "type": "string",
      "description": "Echoed query string for use in follow-up calls."
    }
  },
  "additionalProperties": false
}
gdelt_get_tv_context annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}
gdelt_list_tv_stations — List GDELT TV Stations
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

List the television stations available for TV search with their market, network, monitoring start date, and monitoring end date — every station by default, or only those matching the optional stations, network, and market filters (each an exact, case-insensitive match; combined with AND). activeCount and totalCount count the returned stations. Stations with an end date within the last 24 hours are flagged as active; stations with earlier end dates are discontinued. Use before querying to verify a station was active during the target time period, or to discover valid station IDs for the stations parameter in other TV tools. Archive coverage varies by station; check each station’s monitoring date range. Use the returned network values with network: and market values with quoted market: selectors in TV queries.

gdelt_list_tv_stations input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "market": {
      "type": "string",
      "description": "Market to narrow to (e.g. \"National\", \"San Francisco\"), matched as a whole value case-insensitively after trimming — \"National\" does not match \"NationalSpecialty\". Values come from the market field of the unfiltered list. Blank is ignored."
    },
    "network": {
      "type": "string",
      "description": "Network to narrow to (e.g. \"CNN\", \"ABC\"), matched as a whole value case-insensitively after trimming — \"FOX\" does not match \"FOXNEWS\". Values come from the network field of the unfiltered list. Blank is ignored."
    },
    "stations": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Station IDs to return (e.g. [\"CNN\", \"FOXNEWS\", \"MSNBC\"]) — the IDs the stations parameter of the other TV tools takes. Matches any listed ID, exactly and case-insensitively after trimming; IDs that match no station are named in the notice. Blank entries are ignored; omit it or pass [] to include every station."
    }
  },
  "additionalProperties": false
}
gdelt_list_tv_stations output schema
{
  "type": "object",
  "anyOf": [
    {
      "not": {
        "required": [
          "error"
        ]
      },
      "required": [
        "stations",
        "activeCount",
        "totalCount"
      ]
    },
    {
      "required": [
        "error"
      ]
    }
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "JSON-RPC error code for this failure."
        },
        "data": {
          "type": "object",
          "properties": {
            "reason": {
              "type": "string",
              "examples": [
                "gdelt_rate_limited",
                "gdelt_unavailable"
              ],
              "description": "Machine-readable failure mode. Declared by this tool: `gdelt_rate_limited`: GDELT rejected the request for its one-request-per-five-seconds limit, or too many requests were already queued for this one to start in time. `gdelt_unavailable`: GDELT TV API is unreachable or temporarily returned no usable data, including an empty station catalog. Other values are possible when a failure originates below the handler."
            },
            "recovery": {
              "type": "object",
              "required": [
                "hint"
              ],
              "properties": {
                "hint": {
                  "type": "string"
                }
              },
              "description": "Actionable next step for the caller.",
              "additionalProperties": {}
            },
            "retryable": {
              "type": "boolean",
              "description": "Whether retrying may succeed."
            }
          },
          "additionalProperties": {}
        },
        "message": {
          "type": "string",
          "description": "Human-readable description of what went wrong."
        }
      },
      "description": "Present when the call failed. Absent on success.",
      "additionalProperties": {}
    },
    "notice": {
      "type": "string",
      "description": "Filter outcome: names the filters when no station matched, and names requested station IDs that are not in the catalog or that another filter excluded. Absent when every requested ID was returned and the result is not empty."
    },
    "stations": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "stationId",
          "description",
          "market",
          "network",
          "startDate",
          "endDate",
          "isActive"
        ],
        "properties": {
          "market": {
            "type": "string",
            "description": "Market (e.g. \"National\", \"San Francisco\")."
          },
          "endDate": {
            "type": "string",
            "description": "Monitoring end date in ISO 8601 format."
          },
          "network": {
            "type": "string",
            "description": "Network affiliation (e.g. \"CNN\", \"NBC\")."
          },
          "isActive": {
            "type": "boolean",
            "description": "True when the end date is within the last 24 hours (recently updated feed). False for discontinued stations."
          },
          "startDate": {
            "type": "string",
            "description": "Monitoring start date in ISO 8601 format."
          },
          "stationId": {
            "type": "string",
            "description": "Station ID used in TV query operators (e.g. \"CNN\")."
          },
          "description": {
            "type": "string",
            "description": "Human-readable station description."
          }
        },
        "description": "A single TV station with monitoring metadata.",
        "additionalProperties": false
      },
      "description": "Stations matching every supplied filter — all stations when none is given — sorted by station ID."
    },
    "totalCount": {
      "type": "number",
      "description": "Number of stations returned — the whole catalog when no filter is given."
    },
    "activeCount": {
      "type": "number",
      "description": "Number of returned stations currently flagged as active."
    },
    "staleResponse": {
      "type": "object",
      "required": [
        "fetchedAt",
        "ageSeconds",
        "reason"
      ],
      "properties": {
        "reason": {
          "enum": [
            "gdelt_rate_limited",
            "gdelt_unavailable",
            "gdelt_empty"
          ],
          "type": "string",
          "description": "Why the refetch was not used: GDELT rate-limited it, did not answer with data, or answered empty — which GDELT also does under load."
        },
        "fetchedAt": {
          "type": "string",
          "description": "ISO 8601 time GDELT returned the stored answer."
        },
        "ageSeconds": {
          "type": "number",
          "description": "Age of the stored answer when served, in whole seconds."
        }
      },
      "description": "Present only when the refetch of this exact request was refused, failed, or came back empty, and the response is GDELT's stored answer from fetchedAt instead. It holds nothing published after fetchedAt; a relative timespan covers the window ending at fetchedAt, not now. Absent on a live answer.",
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}
gdelt_list_tv_stations annotations
{
  "readOnlyHint": true,
  "openWorldHint": true
}

Prompts

0 advertised

No prompt definitions available.

Resources

1 advertised

gdelt-guide

Advertised by the server during the last successful anonymous check.

Investigate recent news spikes and compare historical television coverage with gdelt_* tools. Use for theme resolution, evidence searches, station comparisons, or coverage and framing claims that require date-range, identifier, sampling, and completeness checks.

gdelt-guide URI
skill://gdelt-guide/SKILL.md

MIME type: text/markdown

io.modelcontextprotocol/skills

Advertised by the server during the last successful anonymous check.

io.modelcontextprotocol/skills URI template
skill://{+path}

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
652 ms
95th percentile latency
652 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 652 ms · metadata changed · 10 tool(s), 1 resource(s), 1 resource template(s), 0 prompt(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http gdelt-mcp-server-caseyjhand https://gdelt.caseyjhand.com/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add gdelt-mcp-server-caseyjhand --url https://gdelt.caseyjhand.com/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable gdelt-mcp-server-caseyjhand in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "gdelt-mcp-server-caseyjhand": {
      "url": "https://gdelt.caseyjhand.com/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "gdelt-mcp-server-caseyjhand": {
      "type": "streamableHttp",
      "url": "https://gdelt.caseyjhand.com/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start gdelt-mcp-server-caseyjhand and inspect its tools.
VS Code configuration
{
  "servers": {
    "gdelt-mcp-server-caseyjhand": {
      "type": "http",
      "url": "https://gdelt.caseyjhand.com/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http gdelt-mcp-server-caseyjhand https://gdelt.caseyjhand.com/mcp

Claude Desktop

Open Claude Settings > Connectors > Add custom connector, enter this server URL and enable it for the conversation. This is a manual remote-connector handoff, not a desktop JSON configuration.
Claude Desktop configuration
https://gdelt.caseyjhand.com/mcp

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "gdelt-mcp-server-caseyjhand": {
      "serverUrl": "https://gdelt.caseyjhand.com/mcp"
    }
  }
}

Let your agent find its tools

Find servers like gdelt-mcp-server from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.