Skip to main content
Glama

gdelt-mcp

A small MCP server that gives AI assistants reliable access to the GDELT DOC 2.0 API (worldwide online news, 65 languages, rolling 3-month window).

GDELT accepts one request every 5 seconds per IP address. Cloud fetchers and AI tools share their outgoing IP addresses with many other users, so their GDELT calls are often refused with HTTP 429 before they even start. gdelt-mcp runs on a machine with its own address and acts as a polite proxy:

  • one queue for all calls: one GDELT request at a time, at least 6 s apart (configurable, never under 5 s);

  • retries after a 429 with a global back-off (10 s, then 20 s), and a clear error when GDELT stays unavailable;

  • cache: 10 minutes for recent windows, 24 hours for windows that ended more than 3 hours ago; identical concurrent calls are merged; a copy up to 2 hours old is served, flagged stale, if GDELT keeps failing;

  • compact, exact results: tables (columns + rows) instead of pages that a model has to summarise;

  • safe inputs: explicit UTC windows, dates without a timezone are refused, country names and ISO codes mapped to GDELT's names (GDELT's 2-letter codes are FIPS codes: CH is China, not Switzerland).

French installation guide: docs/guide-fr.md.

Tools

Tool

GDELT mode

What it returns

gdelt_search_articles

ArtList

Articles matching a query in a window: [seen, domain, lang, country, title, url], newest first, up to 250 per call, with next_end to page back in time.

gdelt_coverage_timeline

TimelineVolRaw / TimelineSourceCountry / TimelineLang

Matching article counts per day or hour with totals, or the countries / languages whose media cover the query most.

gdelt_topic_trend

2 × TimelineVolRaw

Articles per day in a window versus the baseline_days (default 7) before it: ratio, normalized ratio and a label rising / stable / falling / no_baseline / no_data.

gdelt_topic_summary

TimelineVolRaw + ArtList × pages (+ TimelineSourceCountry)

A topic's worldwide coverage over whole UTC days, in one call: total and daily articles with a data-gap check against the 7 previous days; the period's articles listed newest first, page by page (250 per GDELT request) up to max_articles (default 1000), duplicate URLs and headlines removed; number of source countries; countries ranked by number of articles, exact when articles_listed.complete is true (one country can be left out); languages ranked the same way (top_languages, all of them, the excluded country's media left out); and the newest headlines to check the query.

gdelt_proxy_status

none

Requests made, 429s received, cache and queue state, last success and last error.

Common parameters of the GDELT tools:

  • query — GDELT syntax: keywords, "exact phrase", (a OR b), -excluded. GDELT machine-translates non-English coverage, so English keywords also match articles in other languages.

  • source_country — outlets based in a country: English or French name (Germany, Royaume-Uni) or ISO 3166 code (DE).

  • source_lang — original language: name or ISO code (spanish, es).

  • domain, domain_exact — a single outlet (domain: includes subdomains, domain_exact uses domainis:).

  • start / end (ISO 8601 with timezone, within the last 3 months) or timespan (36h, 3d, 1w); default: the last 24 hours. gdelt_topic_summary takes start_date / end_date (whole UTC days, YYYY-MM-DD) instead.

  • max_articles (gdelt_topic_summary only, 250 to 2000, default 1000) — how far back the article list is read, in pages of 250, one GDELT request (~6 s) per page. When the period holds more articles than this, articles_listed.complete is false, top_countries and top_languages count the newest max_articles only (stopped_by: "max_articles"), and the number of countries comes from the source-country timeline instead of the list.

seen is the time GDELT first saw an article (UTC). It is usually close to the publication time but is not the publication time. GDELT only provides titles and metadata: open the URL to read an article.

Example result of gdelt_search_articles (shortened):

{
  "query": "(Brazil OR Brazilian) election sourcecountry:germany",
  "window": { "start": "2026-09-19T06:00:00Z", "end": "2026-09-22T06:00:00Z" },
  "sort": "date_desc",
  "count": 75,
  "max_records": 75,
  "truncated": true,
  "next_end": "2026-09-20T17:45:00Z",
  "columns": ["seen", "domain", "lang", "country", "title", "url"],
  "rows": [["2026-09-22T05:30:00Z", "example.de", "German", "Germany", "…", "https://…"]],
  "source": { "cached": false, "stale": false, "fetched_at": "2026-09-22T06:00:04Z", "gdelt_url": "https://api.gdeltproject.org/…" }
}

Errors come back as tool errors with a code: invalid_input, gdelt_query_error (GDELT's own message, e.g. a missing parenthesis), gdelt_rate_limited, gdelt_unavailable, proxy_busy (with retry_after_s).

Related MCP server: AllNewsAPI MCP

Deploy on a server (Ubuntu 22.04 / 24.04)

You need a server with its own public IPv4 address, a host name whose A record points to it (a subdomain of your domain, or a free name such as DuckDNS), and ports 80 and 443 open in the provider's firewall (many cloud providers open only SSH on a new server).

curl -fsSLO https://raw.githubusercontent.com/nadirdev1/gdelt-mcp/main/deploy/install.sh
sudo bash install.sh mcp.example.org

The script installs Docker if needed, then picks a mode (MODE=standalone or MODE=proxy forces one):

  • standalone, when ports 80/443 are free: Caddy runs next to the app and gets the HTTPS certificate itself;

  • proxy, when a web server already uses 80/443: the app listens on 127.0.0.1 only. For nginx or Apache, the script offers to add a site for the host name (a new file; nothing else is touched) and to get its certificate with certbot; for other servers (hosting panels, Traefik, Caddy on the host) it prints what to add.

It then generates the access key and prints how to connect:

URL:           https://mcp.example.org/mcp
Header name:   X-API-Key
Header value:  <key>

Add it as a custom connector in your MCP client. In Claude: Settings → Connectors → Add custom connector, with the URL above (choose "Continue anyway" if Claude cannot verify the server: it refuses every request without the key), authentication set to none, and a request header X-API-Key whose value is the key; Claude stores header values encrypted and never shows them again. Authorization: Bearer <key> works too. The key is the secret: anyone who has it can use your GDELT quota.

For clients that cannot send headers, run the installer with ALLOW_TOKEN_IN_URL=true: the key is then also accepted in the URL, https://mcp.example.org/mcp/<key>, which becomes a secret that shows up on screens and in logs. The web server must then not log request paths for this host (the script's nginx and Apache sites disable access logs; Caddy logs nothing by default).

Useful commands on the server:

cd /opt/gdelt-mcp
sudo docker compose ps                           # status
sudo docker compose logs -f app                  # logs (one JSON line per GDELT request)
sudo grep MCP_TOKEN .env                         # show the key

Updating

The server never updates itself. To deploy a version, run on the server:

sudo bash /opt/gdelt-mcp/deploy/update.sh            # latest commit of main
sudo bash /opt/gdelt-mcp/deploy/update.sh v0.3.2     # a tag or a commit

The script shows the running and the target commits, asks for confirmation, fetches the code, rebuilds the image, restarts the app, checks /health and records the deployed commit in /var/lib/gdelt-mcp/deployed. The tests run on GitHub Actions for every push: check that they are green before deploying.

For a private repository, give the server a read-only deploy key once; both settings are kept in .env:

sudo ssh-keygen -t ed25519 -N '' -f /root/.ssh/gdelt-mcp-deploy    # add the .pub as a read-only deploy key on GitHub
sudo REPO_URL=git@github.com:owner/gdelt-mcp.git DEPLOY_KEY=/root/.ssh/gdelt-mcp-deploy bash /opt/gdelt-mcp/deploy/update.sh

Servers installed before 0.3.2 had a systemd timer that deployed main on its own every 30 minutes; install.sh removes it when run again, and docs/guide-fr.md (section 5) gives the manual steps.

Configuration

Environment variables (set in /opt/gdelt-mcp/.env, then sudo docker compose up -d):

Variable

Default

Meaning

MCP_TOKEN

required

Access key, sent by clients in the X-API-Key header (or Authorization: Bearer); 24–128 characters [A-Za-z0-9_-].

ALLOW_TOKEN_IN_URL

true (install.sh writes false)

Also accept the key in the URL path, /mcp/<key>, for clients that cannot send headers.

DOMAIN

required (Docker)

Host name of the server.

APP_PORT

3000 (or the first free port)

Local port the app listens on (127.0.0.1 only).

COMPOSE_PROFILES

caddy in standalone mode

Written by install.sh; absent when another web server is in front.

GDELT_MIN_INTERVAL_MS

6000

Minimum time between two GDELT requests (at least 5000 against the official API).

GDELT_TIMEOUT_MS

20000

Timeout of one GDELT request.

GDELT_CALL_BUDGET_MS

35000

How long a tool call may wait in the queue or back off before giving up.

GDELT_RETRY_DELAY_1_MS, GDELT_RETRY_DELAY_2_MS

10000, 20000

Back-off after the first and second 429 of a call.

CACHE_RECENT_TTL_MS

600000

Cache lifetime for windows ending less than 3 hours ago.

CACHE_SETTLED_TTL_MS

86400000

Cache lifetime for older windows.

CACHE_STALE_MAX_AGE_MS

7200000

Maximum age of a cached copy served when GDELT fails.

CACHE_MAX_ENTRIES

300

Cache size.

PORT, HOST

3000, 0.0.0.0

HTTP listener.

Local development

npm ci
npm test                     # unit tests + end-to-end tests against a mock GDELT, with MCP clients of both protocol eras
npm run build
ALLOW_NO_TOKEN=true PORT=3000 node dist/index.js   # MCP endpoint: http://localhost:3000/mcp

Built with the MCP TypeScript SDK v2: stateless Streamable HTTP, serving both 2026-07-28 clients and 2025-era clients (initialize handshake).

Data and credits

All data comes from The GDELT Project, an open platform whose datasets may be used freely provided GDELT is cited as the source. This proxy respects GDELT's published rate limit; for heavy use, GDELT recommends its bulk datasets instead of the API.

License

MIT

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables searching news articles and retrieving top headlines from the GNews API with support for filtering by topic, language, and country.
    -
  • A
    license
    A
    quality
    A
    maintenance
    Get access to real-time and historical news data including top headlines from global sources via AllNewsAPI. Supports multiple filter options including keyword search, category, language and more
    4
    3
    36 npm
    1
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Provides access to the GDELT DOC 2.0 API for searching global news articles and images across 65 languages with customizable timespans and query options.
    2
    2 npm
    2
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables macro/geopolitical event detection by wrapping the GDELT 2.0 API, providing tools for searching events, trending actors, and sentiment timeseries from global news.
    1
    -