MCP Server

Pure Report — Neutral News

report.pure/news
Media & Content Search & Research Public & reachable MCP 2026-07-28

What this MCP does

Searches neutralized and bias-scored news, provides verification-gated event reports, compares outlet framing, and tracks trending events.

about_pure_report
About & methodology
How Pure Report works — the bias scale, neutralization method, the two-gate verification for event accounts, lean labeling, coverage scope (topic list), and the support contact. Call this to cite the source or explain its methodology to a user.
Read only
Input schema
{'type': 'object', 'properties': {'article_id': {'type': 'integer', 'description': 'Optional context for the report.'}, 'event_slug': {'type': 'string', 'description': 'Optional context for the report.'}, 'report_body': {'type': 'string', 'description': 'Optional. The detail needed to act.'}, 'report_kind': {'enum': ['bug', 'dx', 'data_error', 'data_gap', 'feature', 'question', 'other'], 'type': 'string', 'description': 'Optional, defaults to bug.'}, 'report_subject': {'type': 'string', 'description': 'Optional. Providing this (with report_body) files feedback and returns a ref under "filed" — use only if submit_feedback is missing from your tools.'}}}
Output schema
{'type': 'object', 'required': ['bias_scale', 'support'], 'properties': {'name': {'type': 'string'}, 'filed': {'type': ['object', 'null']}, 'support': {'type': 'string'}, 'website': {'type': 'string'}, 'freshness': {'type': 'string'}, 'bias_scale': {'type': 'string'}, 'what_it_is': {'type': 'string'}, 'lean_labeling': {'type': 'string'}, 'coverage_scope': {'type': 'object'}, 'neutralization': {'type': 'string'}, 'verification_gate': {'type': 'string'}, 'reporting_problems': {'type': 'string'}, 'reporting_problems_if_submit_feedback_is_missing': {'type': 'string'}}}
check_feedback
Check a feedback reply
Look up feedback you filed with submit_feedback, using the ref it returned (e.g. PR-7F3K2Q). Returns the current status (open, answered, closed) and the operator's reply once one exists. Replies are written by a human and are not immediate — poll sparingly, on the order of hours or days, not seconds.
Read only
Input schema
{'type': 'object', 'required': ['ref'], 'properties': {'ref': {'type': 'string', 'description': "The ref from submit_feedback, e.g. 'PR-7F3K2Q'."}}}
Output schema
{'type': 'object', 'required': ['ref', 'status'], 'properties': {'ref': {'type': 'string'}, 'kind': {'type': 'string'}, 'reply': {'type': ['string', 'null']}, 'status': {'type': 'string'}, 'message': {'type': 'string'}, 'subject': {'type': 'string'}, 'replied_at': {'type': ['string', 'null']}, 'submitted_at': {'type': ['string', 'null']}}}
compare_coverage
Compare outlet framing
Show how outlets across the political spectrum framed one event: a per-outlet bias-score spectrum and, where they editorialized, the verbatim framing quotes grouped by left/center/right. The core 'compare the coverage' view — use it to detect slant and consensus.
Read only
Input schema
{'type': 'object', 'required': ['slug'], 'properties': {'slug': {'type': 'string', 'description': 'Event slug from trending_events or a search_news result.'}}}
Output schema
{'type': 'object', 'required': ['slug', 'url'], 'properties': {'url': {'type': 'string'}, 'name': {'type': ['string', 'null']}, 'slug': {'type': 'string'}, 'framing_spectrum': {'type': ['object', 'null']}, 'how_each_side_framed_it': {'type': ['object', 'null']}}}
get_article
Get article
Fetch one article by id: neutral rewritten title + body, a bias_score for the ORIGINAL source (not the rewrite), source, extracted entities, and the events it belongs to.
Read only
Input schema
{'type': 'object', 'required': ['article_id'], 'properties': {'article_id': {'type': 'integer', 'description': 'Numeric article id (from search_news results).'}}}
Output schema
{'type': 'object', 'required': ['id', 'url'], 'properties': {'id': {'type': 'integer'}, 'url': {'type': 'string'}, 'title': {'type': ['string', 'null']}, 'events': {'type': 'array'}, 'content': {'type': ['string', 'null']}, 'summary': {'type': ['string', 'null']}, 'entities': {'type': ['object', 'array', 'null']}, 'bias_score': {'type': ['number', 'null']}, 'source_url': {'type': ['string', 'null']}, 'source_name': {'type': ['string', 'null']}, 'published_at': {'type': ['string', 'null']}}}
get_event
Neutral event writeup
Get the full neutral writeup of one news event by slug: a verification-gated account (lede, what-we-know bullets with verbatim source receipts, single-source attributed items) plus a coverage census (how many outlets by political lean, earliest report). If no gated account exists yet, the coverage census is still returned.
Read only
Input schema
{'type': 'object', 'required': ['slug'], 'properties': {'slug': {'type': 'string', 'description': 'Event slug from trending_events or a search_news result, e.g. "tyler-robinson-trial-for-charlie-kirk-murder".'}}}
Output schema
{'type': 'object', 'required': ['slug', 'coverage', 'url'], 'properties': {'url': {'type': 'string'}, 'name': {'type': ['string', 'null']}, 'slug': {'type': 'string'}, 'status': {'type': ['string', 'null']}, 'account': {'type': ['object', 'null']}, 'coverage': {'type': 'object'}, 'first_seen': {'type': ['string', 'null']}, 'account_note': {'type': ['string', 'null']}, 'article_count': {'type': ['integer', 'null']}, 'coverage_report': {'type': ['object', 'null']}}}
search_news
Search neutral news
Search Pure Report's neutral, bias-scored news. Returns articles rewritten to remove loaded language; bias_score (0-100) rates the ORIGINAL source reporting before neutralization (0 = wire-neutral, 100 = advocacy), NOT the returned rewrite, which is neutral by design. Each result also lists the event(s) it belongs to — pass an event slug to get_event for the neutral writeup or compare_coverage for cross-outlet framing. Ranked by relevance and recency.
Read only
Input schema
{'type': 'object', 'required': ['query'], 'properties': {'limit': {'type': 'integer', 'description': 'Max results to RETURN, 1-40 (default 15). Does not affect total_matches, which always reports how many articles matched.'}, 'query': {'type': 'string', 'description': 'Keywords or phrase, e.g. "Iran sanctions" or "2026 election".'}, 'topic': {'enum': ['politics', 'business', 'world', 'technology', 'health', 'science', 'justice', 'defense', 'climate-energy', 'media', 'education', 'culture', 'sports', 'local', 'opinion', 'real-estate'], 'type': 'string', 'description': 'Optional topic-slug filter. An unrecognized value searches all topics and returns a warning.'}, 'offset': {'type': 'integer', 'description': 'Skip this many matches — page through results beyond the 40-row limit. The response echoes offset/returned/next_offset; next_offset is null on the last page.'}, 'published_after': {'type': 'string', 'description': "Only articles published on/after this date. 'YYYY-MM-DD' or full ISO. Use with published_before to bound a period, e.g. coverage during June."}, 'published_before': {'type': 'string', 'description': "Only articles published on/before this date. 'YYYY-MM-DD' or full ISO."}}}
Output schema
{'type': 'object', 'required': ['query', 'total_matches', 'results'], 'properties': {'query': {'type': 'string'}, 'offset': {'type': 'integer'}, 'results': {'type': 'array', 'items': {'type': 'object', 'properties': {'id': {'type': 'integer'}, 'url': {'type': 'string'}, 'title': {'type': ['string', 'null']}, 'events': {'type': 'array', 'items': {'type': 'object', 'properties': {'name': {'type': ['string', 'null']}, 'slug': {'type': 'string'}}}}, 'source': {'type': ['string', 'null']}, 'summary': {'type': ['string', 'null']}, 'bias_score': {'type': ['number', 'null']}, 'published_at': {'type': ['string', 'null']}}}}, 'warning': {'type': 'string'}, 'returned': {'type': 'integer'}, 'next_offset': {'type': ['integer', 'null']}, 'applied_topic': {'type': ['string', 'null']}, 'total_matches': {'type': 'integer', 'description': 'TOTAL articles matching the query, independent of `limit` — not the number returned. len(results) < total_matches means more exist.'}, 'result_composition': {'type': 'object', 'description': 'Factual description of what the returned set is ABOUT. Search is lexical, so every query term appears in every result; this reports whether a term is the SUBJECT (title/entities/lede) or only a body mention, plus the entity distribution. Measurements only — no verdict.'}}}
submit_feedback
Send feedback to the operator
Report a problem or request to Pure Report's operator and get a tracking ref back. Use this when the data looks wrong — a bias score or outlet lean that doesn't match the source, an event cluster mixing unrelated stories, a missing neutral writeup, a broken article — or to ask a methodology question or request a capability. Include the article_id or event_slug you were looking at; that context is what makes a report actionable. A human reads these: replies take time and are not guaranteed. Call check_feedback with the returned ref to read the reply.
Input schema
{'type': 'object', 'required': ['subject', 'body'], 'properties': {'body': {'type': 'string', 'description': 'The detail needed to act: what you expected, what you got, and how to reproduce it. Max 12000 chars.'}, 'kind': {'enum': ['bug', 'dx', 'data_error', 'data_gap', 'feature', 'question', 'other'], 'type': 'string', 'description': 'DEPRECATED alias for category; still accepted.'}, 'subject': {'type': 'string', 'description': 'One line, max 200 chars.'}, 'category': {'enum': ['bug', 'dx', 'data_error', 'data_gap', 'feature', 'question', 'other'], 'type': 'string', 'description': 'bug = broken or erroring; dx = developer-experience friction; data_error = wrong/miscategorised data; data_gap = missing coverage or field; feature = a capability request; question = methodology or usage; other. Defaults to bug.'}, 'article_id': {'type': 'integer', 'description': 'Optional article the report concerns.'}, 'event_slug': {'type': 'string', 'description': 'Optional event slug the report concerns.'}}}
Output schema
{'type': 'object', 'required': ['ref', 'status'], 'properties': {'ref': {'type': 'string'}, 'status': {'type': 'string'}, 'message': {'type': 'string'}, 'how_to_check': {'type': 'string'}}}
trending_events
Trending news events
List the news events with the most current coverage activity. Each event clusters many outlets' articles about one story and includes has_account (boolean): true means get_event returns a full verification-gated writeup, false means only the coverage census is available yet. Returns slugs to pass to get_event / compare_coverage.
Read only
Input schema
{'type': 'object', 'properties': {'limit': {'type': 'integer', 'description': 'Max events, 1-25 (default 10).'}}}
Output schema
{'type': 'object', 'required': ['events'], 'properties': {'events': {'type': 'array', 'items': {'type': 'object', 'properties': {'url': {'type': 'string'}, 'name': {'type': ['string', 'null']}, 'slug': {'type': 'string'}, 'first_seen': {'type': ['string', 'null']}, 'has_account': {'type': 'boolean'}, 'article_count': {'type': ['integer', 'null']}}}}}}
Added
check_feedback
Sept. 17, 2026, 12:54 p.m.
Added
submit_feedback
Sept. 17, 2026, 12:54 p.m.
Added
about_pure_report
Sept. 17, 2026, 12:54 p.m.
Added
get_article
Sept. 17, 2026, 12:54 p.m.
Added
compare_coverage
Sept. 17, 2026, 12:54 p.m.
Added
get_event
Sept. 17, 2026, 12:54 p.m.
Added
trending_events
Sept. 17, 2026, 12:54 p.m.
Added
search_news
Sept. 17, 2026, 12:54 p.m.