Docs

NewsMCP documentation

NewsMCP is an MCP server: five tools that give an agent live news as story events rather than articles — every outlet covering the same story is grouped into one object. There is also a plain REST API underneath it, but this page is written for the MCP surface. No key is required to start.

The reference tables on this page — tool parameters, taxonomy values, limits — are generated from the MCP server's own tool definitions and the API's OpenAPI document, so they cannot drift from the service. Prose is written by hand.

NewsMCP APIChangelog

Quickstart

Nothing to install and no signup. Point any MCP client at the hosted endpoint:

https://mcp.newsmcp.com/mcp

Streamable HTTP, stateless — no initialize handshake or session id required. Keyless works immediately; a key raises the limits (see Access and limits) and is free to get at platform.newsmcp.com/auth — sign up, no waitlist.

Claude Code

Keyless:

claude mcp add --transport http newsmcp https://mcp.newsmcp.com/mcp

With a key:

claude mcp add --transport http newsmcp https://mcp.newsmcp.com/mcp \
  --header "x-api-key: <your-key>"

Claude Desktop — add to claude_desktop_config.json, then restart:

Keyless:

{
  "mcpServers": {
    "newsmcp": { "url": "https://mcp.newsmcp.com/mcp" }
  }
}

With a key — Desktop's config has no headers field, so pass it in the URL:

{
  "mcpServers": {
    "newsmcp": { "url": "https://mcp.newsmcp.com/mcp?apiKey=<your-key>" }
  }
}

Cursor — add to ~/.cursor/mcp.json, or use the one-click deeplink below:

Keyless:

{
  "mcpServers": {
    "newsmcp": { "url": "https://mcp.newsmcp.com/mcp" }
  }
}

With a key:

{
  "mcpServers": {
    "newsmcp": {
      "url": "https://mcp.newsmcp.com/mcp",
      "headers": { "x-api-key": "<your-key>" }
    }
  }
}
cursor://anysphere.cursor-deeplink/mcp/install?url=https%3A%2F%2Fmcp.newsmcp.com%2Fmcp&name=newsmcp

VS Code — add to .vscode/mcp.json in your workspace:

Keyless:

{
  "servers": {
    "newsmcp": { "type": "http", "url": "https://mcp.newsmcp.com/mcp" }
  }
}

With a key:

{
  "servers": {
    "newsmcp": {
      "type": "http",
      "url": "https://mcp.newsmcp.com/mcp",
      "headers": { "x-api-key": "<your-key>" }
    }
  }
}

Any other MCP client — including OpenAI's Responses API connectors and other hosts that speak streamable HTTP — needs only the URL above; add a key with whichever method its config supports, from the table below.

Adding a key#

#MethodWherePrecedence
1api_key tool argumentPassed in a single tool call, e.g. news(api_key="...")Highest
2x-api-key headerSet on the MCP client's connection config
3Authorization: Bearer <token>Set on the MCP client's connection config
4?apiKey=... URL parameterAppended to the MCP URL (apikey / api_key also accepted)
5NEWSMCP_API_KEY env varSelf-hosted / local stdio runs only (NEWSMCP_API_TOKEN still read, deprecated)Lowest

Get a key at platform.newsmcp.com/auth.

Agents

If you are an AI agent reading this, the machine-readable contract is at /agent-onboarding/SKILL.md. This page is generated from the MCP server's own tool definitions and the REST API's openapi.json.

Events, not articles

A search does not return a flat list of articles. It returns events: every article covering the same story is grouped into one of them.

A widely covered story therefore arrives as a single object rather than a hundred near-identical rows, and the corroboration counts become the useful signal:

FieldMeaning
newsroomsOutlets that reported independently, mirrors excluded.
source_countDistinct domains reached, mirrors included.
reportsArticles in the cluster.
sizeCluster members.
language_countDistinct languages the story appeared in.
mirror_ratioShare of the cluster that is syndicated copy.
confidenceCertainty of the taxonomy label, 0-1.

min_sources counts domains with mirrors included — a site that only republished someone else's copy still counts. min_newsrooms excludes them. When you want "is this a real story", newsrooms is the stronger signal.

Article body text is never returned. sources carries links; follow them to the publisher.

Tools

ToolUse it for
newsSearch or filter synthesized story events — the general-purpose surface.
Default choice: a topic, a filter, or a bare call for the most-corroborated recent stories.
get_storyExpand one story by id — full summary and, on request, every source link.
After any search, when the user wants more than the digest line, or the complete source list.
check_coverageJudge whether a claim is real — independent newsrooms, not domain count.
“Is this actually true?” rather than “what happened.”
check_limitsThis caller's live allowances — free to call, spends nothing.
Before planning a batch of calls, or right after any limit error, instead of guessing.
check_healthConfirm the API is reachable — a liveness ping, not a search.
Diagnosing connectivity. Never for finding news — use check_limits for allowances.

news is the general surface — a topic, a filter, or a bare call for the most-corroborated recent stories. For a named company, person or place, use its subject parameter rather than q: it quotes the name so it matches as a phrase and widens the window to 30 days. Both matter — q=Bank of America unquoted returns "India Now Asia's Least Preferred Stock Market" first, and q=Monzo over the default 24 hours returns nothing. check_coverage answers a different question again — not "what happened" but "is this real", reporting independent newsrooms separately from syndicated reprints.

Upstream clustering is currently siloed by language, so one story can appear as several events with different generated headlines. check_coverage totals those variants and shows what it combined.

Parameters

Each tool below takes only the parameters listed for it — passing one from a different tool is rejected, not ignored.

news#

ParameterTypeDefaultWhat it does
qstringKeyword query over headline, one-liner, abstract and actor names. Bare words are ANDed — quote a multi-word phrase next to OR/AND/NOT: layoffs OR "workforce reduction". No stemming, and NEAR()/MULTIPLE() are not supported. Conversational filler is stripped before the search runs, so a natural-language question no longer comes back empty; quoted phrases are never touched. Omit for a filter-only digest.
subjectstringA single company, person or place to centre on — quoted for you automatically and ANDed with q. Also widens the default window to 30 days, since a company can go quiet for a week; pass from_ to override.
event_idstringFetch one story by its id; every other filter is ignored. Prefer get_story — same result, and it can return the full source list.
event_typestringWhat kind of event the story is, as family.leaf. Comma-separated for OR. See Taxonomy.
content_typestringThe form the reporting takes. Comma-separated for OR. See Taxonomy.
sectorstringIndustry the story belongs to. Comma-separated for OR. See Taxonomy.
min_newsroomsintegerMinimum outlets that reported independently, mirrors excluded — the strongest is-this-real filter. 3 ≈ “well-corroborated only.”
from_string24 hours agoInclusive start of the window over when the story began — not when any one article was published. ISO 8601 or a relative phrase (“2 days ago”). Capped per plan; widen this first when a query returns nothing.
sortstringAPI choosesWhat “best” means. Omit it — the API already picks relevance with a query and newsrooms without, which is almost always right. trending weights corroboration by an 8-hour freshness half-life.
limitinteger20Stories per call, 1–50, capped by plan (keyless 20, free tier 50). A flat ceiling, not a page size — there is no paging past it.
verbositystringstandardControls only the source-link count — headline, summary, actors and labels are always present. compact: none. standard: up to 3. full: every link, uncapped.
response_formatstringmarkdownShape of the reply: markdown digest, text plain lines, or json the full payload.
api_keystringPer-call API key, forwarded as x-api-key. Highest-precedence override — see Quickstart.

q is rewritten before it runs. A conversational question used to come back empty — what is happening with Iran and sanctions returned nothing, because a mid-query and makes the engine treat what, is and with as required terms, and happening is a required term either way. Filler like that is now dropped, so the same words return results. Quoted phrases, acronyms in caps, and capitalised names are left alone, and if trimming would be ambiguous the query is sent exactly as you wrote it.

Any rewrite is reported: markdown and text replies carry a leading Note: line, and in json the query that actually ran is in applied_filters.search_text. This is an MCP-only convenience — the REST endpoint searches the string you give it.

get_story#

ParameterTypeDefaultWhat it does
event_idstringrequiredThe story's id from an earlier result. A story folded into a more complete one answers not-found, naming the replacement id — fetch that instead.
include_sourcesbooleanfalsefalse returns a sample of source links; true returns every one. The only tool that can return a story's complete source list.
response_formatstringmarkdownmarkdown, text, or json.
api_keystringPer-call API key.

check_coverage#

ParameterTypeDefaultWhat it does
claimstringrequiredThe claim or headline, phrased the way a headline would be. Matched literally, not by meaning — restate it in newsroom words if nothing comes back. Conversational filler is stripped first, same as news's q.
days_backinteger14How far back to look, in days. Clamped down to whatever the caller's plan allows, with a note saying so.
response_formatstringmarkdownmarkdown verdict, text, or json.
api_keystringPer-call API key.

check_limits#

ParameterTypeDefaultWhat it does
response_formatstringtexttext summary or json — no markdown option.
api_keystringReport the ceilings for this key's plan; omit for the keyless ceilings.

check_health#

No parameters.

Taxonomy

Three independent axes. event_type is what happened, content_type is the form the writing takes, sector is the industry. Each accepts a comma-separated list for an OR match, and each rejects a value outside its set — the error names every accepted value, so a wrong guess is self-correcting.

event_type#

60 leaves across 22 families.

FamilyLeaves
corporate_financeearnings_report analyst_rating dividends
marketsstock_move commodity_price currency_move
dealsmerger_acquisition ipo_filing asset_sale
governanceboard_change shareholder_vote executive_departure
society_environmentclimate_event public_health environmental_incident
sportsmatch_result transfer_signing championship
justice_crimearrest_charge trial_verdict investigation
securitycyberattack data_breach physical_security_incident
macro_policycentral_bank_decision trade_policy fiscal_policy
research_sciencescientific_discovery clinical_trial_result publication
religion_societyreligious_event social_movement
politicselection policy_announcement diplomacy
legal_regulatoryregulatory_action lawsuit_filed compliance_ruling
culture_mediacelebrity_news entertainment_release award
productproduct_launch product_recall feature_update
accidents_disastersnatural_disaster industrial_accident transport_accident
operationsplant_closure layoffs supply_chain_disruption
fundingventure_funding_round grant_award
local_civiclocal_government_action infrastructure_project
geopoliticsarmed_conflict sanctions diplomacy_summit
corporate_commspress_release leadership_statement
unclassifiableunclassifiable

content_type#

news_reportpress_releaseservice_infohuman_interestexplainer
commentaryanalysisopinioninterviewobituary

sector#

government_public_sectormedia_entertainmentfinancial_serviceshealthcare_pharma
energy_utilitiesretail_consumerreal_estateagriculture_food
telecommunicationsautomotivemanufacturing_industrialtransport_logistics
aerospace_defensemining_metalsconstruction_infrastructureeducation
hospitality_travelsports_recreationnonprofit_ngolegal_services
insurancesoftware_it_servicesecommercebanking
defense_securitychemicalsfashion_apparelgaming_esports
biotechnologysemiconductorsother_sector

Response shape

Every tool's reply lives in one place: content[0].text. There is no structuredContent to inspect instead.

Toolresponse_formatAlso controls
newsmarkdown, text, jsonverbosity: compact / standard / full — controls only the source-link count
get_storymarkdown, text, jsoninclude_sources: false / true — the only tool with the complete source list
check_coveragemarkdown, text, json
check_limitstext, json — no markdown
check_healthplain string — no response_format

If you intend to parse the result, pass response_format: "json" — don't regex the markdown digest.

A news or get_story event in json looks like this:

{
  "event_id": "evt_1847a4931a6c8002",
  "headline": "White House summons AI labs after models go rogue",
  "one_liner": "Meta, Anthropic, OpenAI and Google were invited to a closed-door briefing.",
  "abstract": "Following a string of high-profile model failures, the White House ...",
  "event_type": "legal_regulatory.regulatory_action",
  "sector": "software_it_services",
  "content_type": "news_report",
  "size": 125,
  "source_count": 41,
  "newsrooms": 18,
  "first_seen": "2026-08-20T09:12:00",
  "last_seen": "2026-08-24T11:03:00",
  "entities": [{"name": "OpenAI"}, {"name": "Anthropic"}],
  "sources": ["https://www.independent.co.uk/tech/...", "https://apnews.com/article/..."]
}

event_id is derived from cluster membership, so the same story can carry a different id on a later search — don't store it.

Access and limits

KeylessFree TierHigher plans
Calls per hour2050per plan
Lookback7 days14 daysper plan
Events per call2050limit accepts 1–50; the plan caps what you actually get
Concurrent calls11per plan
Commercial useyesyesyes

Read your own ceilings with check_limits — it is exempt from metering, so asking costs nothing and is the only number worth trusting, including against this table.

Asking for more than a plan allows behaves in three different ways, and the difference matters when you are debugging an empty result.

Keyless narrows and says so. The search runs against the reduced window and the response carries notices naming every value it changed — surfaced as a leading Note (keyless): line in a markdown/text reply, or a notices array in json.

A keyed plan asked for a window beyond its lookback returns nothing, quietly. Measured on the free tier: a from_ 30 days back against a 14-day plan comes back with no events and no notice. It reads as "no news matched" rather than "outside your plan" — call check_limits before concluding the index is empty.

limit above what the plan allows is a hard error, not a narrowing — the message names the caller's real ceiling.

Every plan, keyless included, carries a full commercial licence. Keys are self-serve at platform.newsmcp.com/auth.

Troubleshooting

SymptomMeansDo
A tool call rejects response_formatThe value wasn't one of the ones that tool accepts — check_limits only takes text/json, no markdown.Use an exact accepted value; the error names them.
sort='relevance' is rejectedrelevance ranks by match quality against q, so it requires q or subject.Add q/subject, drop sort and let the API choose, or use sort='trending'.
get_story or event_id on news answers not-foundThe id doesn't resolve — it's stale, or the story was folded into a more complete one.If a replacement id is named, fetch that one instead; otherwise search again for a current id.
A parameter was rejected, naming itAn event_type, content_type or sector value outside the accepted set.The message lists every accepted value — see Taxonomy, and pick from it.
A value exceeds this plan's maximumAsked for more than a keyed plan allows — limit too high, or from_ too far back.Re-issue once with the value clamped to the maximum the message states. Keyless narrows silently instead of erroring — see Access and limits.
The hourly call budget is spentA 429 with retry_after_seconds — the caller's per-hour allowance ran out.Wait retry_after_seconds; don't retry in a loop. check_limits reports when it resets.
A call is refused with no wait quotedTwo calls were in flight at once — every caller gets exactly one concurrent request.Let the first call finish before sending the next. Never call these tools in parallel.
Empty resultsThe filters genuinely match nothing, or the story hasn't started within the window.Widen from_ first — it bounds when the story began, not when an article was published — then lower a min_* floor.
A call is refused naming the search index as overloaded or unreachableNot your request's fault — the error names the overload rather than a rejected parameter.Retry once after a few seconds; if it fails again, treat it as an outage and stop — retrying in a loop won't clear it.

Example asks

You rarely name a tool or its parameters directly. These are all valid things to say to an MCP-capable client, with what each one resolves to:

What you askToolWhat it sets
“What are the biggest stories today?”newsa bare call — the defaults are exactly this
“What's trending in funding rounds right now?”newsevent_type=funding.venture_funding_round, sort=trending
“Only well-corroborated cybersecurity stories”newsevent_type=security.cyberattack, min_newsrooms=3
“Recalls in the last 7 days”newsevent_type=product.product_recall, from_="7 days ago"
“What's going on with Monzo?”newssubject="Monzo"
“Just the analysis pieces, not straight news”newscontent_type=analysis
“Tell me more about that one”get_storyevent_id from the earlier result
“Show me every source for that story”get_storyevent_id, include_sources=true
“Is that actually true?”check_coverageclaim
“How much quota do I have left?”check_limitsno arguments
“Is NewsMCP up right now?”check_healthno arguments