
Wraps The Guardian's Open Platform API to search and retrieve full article text from their journalism archive spanning 1999 to present. You get three tools: full-text search with section, tag, contributor, and date filters; single-article retrieval by path slug; and a browse mode that surfaces sections, tags, and latest content. Body text comes back HTML-stripped and truncated at 2,000 words with a flag telling you when to fetch the complete version. Needs a free Guardian API key from their developer program. Useful when you're building research tools, news aggregators, or anything that needs access to quality journalism with proper metadata and contributor attribution rather than scraping.
Public tool metadata for what this MCP can expose to an agent.
verify_recipeVerify a candidate recipe against a Guardian master recipe. Uses deterministic graph-based verification to check technique, temperature, timing, cooking medium, and required ingredients. Returns a formatted text report. In Oracle Mode (default), proprietary data is protected —...4 paramsVerify a candidate recipe against a Guardian master recipe. Uses deterministic graph-based verification to check technique, temperature, timing, cooking medium, and required ingredients. Returns a formatted text report. In Oracle Mode (default), proprietary data is protected —...
candidate_jsonvaluedishvaluedish_namestringoriginal_promptvaluelist_dishesList all available dish slugs from the Guardian registry. Returns: Dictionary with canonical dish slugs and their aliases.1 paramsList all available dish slugs from the Guardian registry. Returns: Dictionary with canonical dish slugs and their aliases.
cuisine_filterstringSearch, 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–present), via the Guardian Open Platform API. Search full text, browse by section or tag, and fetch individual articles from any MCP client. Runs as a stdio process or a local Streamable HTTP server.
| 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, invalid_date. Dates must be real calendar dates, including leap-year rules; blank bounds are omitted before calling the API.tag accepts comma (AND), pipe | (OR), hyphen - (NOT), and parentheses. For example, environment/climate-crisis|environment/flooding. When adding contributor: "profile/georgemonbiot", group the expression as (environment/climate-crisis|environment/flooding); the two filters are comma-joined unchanged.guardian_get_article toolarticle_id: the path-slug id returned by guardian_search_articles or guardian_browse_contenttruncatednot_found.guardian_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, tag_not_found. tag_id in tag_latest accepts the same boolean expressions as search's tag.All three tools use authored Guardian error messages and canonical status/body diagnostic fields, without request URLs or duplicate aliases. HTTP failures preserve status-specific error codes. unauthorized (401), access_denied (403), request_rejected (400), validation_failed (422), invalid_request, request_conflict, and request_not_found are explicitly nonretryable and carry parameter or configuration recovery. Article/section 404 retain not_found/section_not_found. api_timeout (408/425/504), rate_limited (429), and api_error (other 5xx) are retryable after the existing three internal retries. api_unsupported (501) is nonretryable and is attempted once. Each reason's recovery hint and retryability appear on both client surfaces.
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 state; when true, call guardian_get_article with its id as article_id for complete HTML-stripped text without a word cap.total / 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.
GUARDIAN_API_KEY*API key for The Guardian Open Platform (https://open-platform.theguardian.com/).
MCP_LOG_LEVELdefault: infoSets the minimum log level for output (e.g., 'debug', 'info', 'warn').
MCP_HTTP_HOSTdefault: 127.0.0.1The hostname for the HTTP server.
MCP_HTTP_PORTdefault: 3010The port to run the HTTP server on.
MCP_HTTP_ENDPOINT_PATHdefault: /mcpThe endpoint path for the MCP server.
MCP_AUTH_MODEdefault: noneAuthentication mode to use: 'none', 'jwt', or 'oauth'.