Guardian Open Platform: search and retrieve full article text from The Guardian archive.
Runs on your machine from its package; the steps are below.
At most: only reads or looks up information.
Odel charges nothing per call. The publisher may charge for its own service.
Runs locally over stdio
This server isn't hosted — your MCP client launches it from a package registry. Use one of the commands below, or drop the config into your client (e.g. Claude Desktop).
Run
npx -y @cyanheads/guardian-mcp-server
MCP client config
{
"mcpServers": {
"guardian": {
"command": "npx",
"args": [
"-y",
"@cyanheads/guardian-mcp-server"
]
}
}
}Run
npx -y @cyanheads/guardian-mcp-server
MCP client config
{
"mcpServers": {
"guardian": {
"command": "npx",
"args": [
"-y",
"@cyanheads/guardian-mcp-server"
]
}
}
}Search, browse, and retrieve full article text from The Guardian's journalism archive (1999–present) via MCP. STDIO or Streamable HTTP.
The Guardian's journalism archive, 1999 to today. Search full text, browse by section or tag, and fetch individual articles.
| Tool | Description |
|---|---|
guardian_search_articles | Full-text search across The Guardian's archive with optional section, tag, contributor, and date filters |
guardian_get_article | Fetch a single Guardian article by ID with body text and metadata |
guardian_browse_content | Browse by section or tag, or discover available sections and tags, across four modes |
guardian_search_articles toolquery syntax (AND/OR/NOT, quoted phrases), optional section/tag/contributor and from_date/to_date (YYYY-MM-DD) filters; order_by: relevance (default), newest, or oldest; page + page_size (1–50, default 10)truncated flag; results include total, page, pages, page_size, and order_byno_results or invalid_date (dates must be real calendar dates)tag accepts comma (AND), pipe | (OR), hyphen - (NOT), and parentheses, e.g. environment/climate-crisis|environment/flooding. Wrap an OR expression in parentheses when also passing contributor.guardian_get_article toolarticle_id: the path-slug id returned by guardian_search_articles or guardian_browse_contenttruncatednot_foundguardian_browse_content toolmode values: section_latest (requires section_id), tag_latest (requires tag_id), list_sections, list_tags; page + page_size (1–50, default 10) for articles and tagslist_tags filters by optional query and tag_type (keyword, contributor, blog, series, tone, type, publication, newspaper-book, newspaper-book-section); output carries mode, total, and the matching results/sections/tags arraymissing_section_id, missing_tag_id, section_not_found, or tag_not_found. tag_id accepts the same boolean expressions as search's tag.All three tools also fail with status-specific HTTP errors. Not retryable: unauthorized (401), access_denied (403), request_rejected (400), validation_failed (422), invalid_request, request_conflict, request_not_found, and api_unsupported (501). Retryable: api_timeout (408/425/504), rate_limited (429), and api_error (other 5xx). Each error carries a recovery hint.
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
Guardian-specific:
guardian_browse_content mode list_tags with tag_type=contributorlist_sections, list_tags) for filter discovery before searchingAgent-friendly output:
truncated; call guardian_get_article for the full texttotal / page / pages on every paginated response so callers can track result scopeAdd the following to your MCP client configuration file. Register for a free Guardian Open Platform API key at open-platform.theguardian.com/access.
{
"mcpServers": {
"guardian-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/guardian-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"GUARDIAN_API_KEY": "your-api-key"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"guardian-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/guardian-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"GUARDIAN_API_KEY": "your-api-key"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"guardian-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "GUARDIAN_API_KEY=your-api-key",
"ghcr.io/cyanheads/guardian-mcp-server:latest"
]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 GUARDIAN_API_KEY=your-api-key bun run start:http
# Server listens at http://localhost:3010/mcp
git clone https://github.com/cyanheads/guardian-mcp-server.git
cd guardian-mcp-server
bun install
cp .env.example .env
# Edit .env and set GUARDIAN_API_KEY
| Variable | Description | Default |
|---|---|---|
GUARDIAN_API_KEY | Required. Free developer key from open-platform.theguardian.com/access. | — |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | Port for HTTP server. | 3010 |
MCP_SESSION_MODE | HTTP session mode: stateless, stateful, or auto (resolves to stateful). The server declares stateless; an exported value overrides it. | stateless |
MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (RFC 5424). | info |
LOGS_DIR | Directory for log files (Node.js only). | <project-root>/logs |
LOG_TOOL_FAILURE_PAYLOADS | Log failed tool arguments and results, redacted by key name and capped by LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES (default 16384). Secrets in free-form values remain visible. | false |
STORAGE_PROVIDER_TYPE | Storage backend. | in-memory |
OTEL_ENABLED | Enable OpenTelemetry instrumentation (spans, metrics, completion logs). | false |
OTEL_EXPORTER_OTLP_ENDPOINT | Base OTLP URL; traces use /v1/traces, metrics use /v1/metrics. | — |
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT | Opt-in OTLP log endpoint, used as-is. | — |
See .env.example for the full list of optional overrides.
Build and run:
# One-time build
bun run rebuild
# Run the built server
bun run start:stdio
# or
bun run start:http
Run checks and tests:
bun run devcheck # Lint, format, typecheck, security
bun run test # Vitest test suite
bun run lint:mcp # Validate MCP definitions against spec
docker build -t guardian-mcp-server .
docker run --rm -e GUARDIAN_API_KEY=your-api-key -p 3010:3010 guardian-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/guardian-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers tools and initializes the Guardian service. |
src/config | Server-specific environment variable parsing (GUARDIAN_API_KEY). |
src/mcp-server/tools | Tool definitions (*.tool.ts): guardian_search_articles, guardian_get_article, guardian_browse_content. |
src/services/guardian | Guardian Open Platform API client, normalization, and type definitions. |
tests/ | Unit and integration tests. |
docs/ | Design document and directory tree. |
See CLAUDE.md / AGENTS.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for request-scoped logging, ctx.state for tenant-scoped storagecreateApp() tools array in src/index.tsIssues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
Apache-2.0 — see LICENSE for details.
Powered by The Guardian.