Stable News MCP
Provides a daily morning news edition ranked by published rules, written in the provider's own words with links to outlets. Users can sign in to receive personalized editions based on their work interests, access audio podcasts, and search recent news history.
Endpoint and access
No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.
https://stablenews.ai/mcp/newsWhat its tools do
13 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.
Can change data (4)
Checks and signals
Each line is separate evidence, not a trust score.
- Passed Endpoint answered the live check ·
- Passed Official MCP Registry namespace is tied to stablenews.ai ·
- Passed Endpoint is on the registry namespace domain ·
- Availability 1 of 1 checks passed in 30 days
What you can do with it
- Receive a daily morning news edition
- Search news from the last two weeks
- Listen to audio versions of editions
- Get personalized news based on work interests
Source and maintenance
Protocol and capabilities
- Server
- Stable News 1
- MCP protocol negotiated in check
- 2025-11-25
- Tools
- 13 advertised
- Resources
- 1 advertised
- Resource templates
- 0 advertised
- Prompts
- 1 advertised
{
"tools": {
"listChanged": true
},
"logging": {},
"prompts": {
"listChanged": true
},
"resources": {
"subscribe": false,
"listChanged": true
}
}Server-provided instructions
Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.
Tools
13 advertised
morning — Morning edition
The day's edition: the briefing's lines by section, each with its countries, who it is about, its score (the story's main at the edition's home, 0-1) and `mains` (the main at home and at the world), our story page and the outlet, and what was read for it. With no `edition`, the reader's own (made each morning from their interests; its `own` note says whether it is ready), else the World edition. `edition` world, pl or us names a public edition; `date` YYYY-MM-DD (the latest when omitted); `audio` adds the edition read aloud.
{
"type": "object",
"properties": {
"date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"audio": {
"type": "boolean",
"default": false
},
"edition": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}top — Top stories
The stories of the last 24 hours in rank order, run again hourly (`as_of`, `window_hours`): each story's rank, our title, its score (0-1: the edition's perspective, its mains pulled by the edition's stakes), `mains` (the main at the edition's home and at the world, the honest pair), its outlets, our story page, and a piece to ask `why` about. With `country`, the stories about it, and a note when we read few of its outlets.
{
"type": "object",
"properties": {
"limit": {
"type": "integer",
"default": 10
},
"country": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "ISO 3166-1 alpha-2, such as FI: only the stories about that country."
},
"edition": {
"type": "string",
"default": "world"
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}why — Why it is here
Why a piece's story is where it is on the list: its rank and score, the mains at the edition's home and at the world, the pulls that lifted it (each stake the edition holds, its step, the main it read and its part of the score, with the arithmetic), the gates that cut a main (no outlet abroad told it, a routine notice), who carried it, who it is about, what is just above and below, and what near it was left out and why.
{
"type": "object",
"required": [
"item_id"
],
"properties": {
"date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"edition": {
"type": "string",
"default": "world"
},
"item_id": {
"type": "integer"
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}search — Search the news
The stories of the last `days` whose pieces name the query, one row a story, in our words with its lead piece's outlet and link, our story page, how many pieces it was found in, its outlets and days, its score and its place on today's list: today's list first, then by score, then the newest. Costs one credit (the balance comes back); the same search the same day is paid once. A row's `item_id` asks `why`, and with its title goes into a draft's examples for save_interest.
{
"type": "object",
"required": [
"query"
],
"properties": {
"days": {
"type": "integer",
"default": 14,
"maximum": 14,
"minimum": 1,
"description": "The last days searched."
},
"limit": {
"type": "integer",
"default": 10,
"maximum": 50,
"minimum": 1,
"description": "Stories given."
},
"query": {
"type": "string",
"description": "Names, OR between them (at most 5): whole words, `*` any letters after three of the name's own."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}save_interest — Save an interest
Move one of the reader's magnets, what draws their own edition: a `target` and a step (away, low, normal, high) saves at once. For a subject no target names, a `draft` of their own words: without `preview` it answers what the draft would give a day, the pieces it finds, and a `confirm` digest; with preview=<confirm> it saves. Their own words are the cause. The same move again changes nothing.
{
"type": "object",
"required": [
"amplitude",
"cause"
],
"properties": {
"note": {
"anyOf": [
{
"type": "string",
"maxLength": 300
},
{
"type": "null"
}
],
"default": null
},
"cause": {
"type": "string",
"maxLength": 300,
"minLength": 1,
"description": "The reader's own words, kept verbatim as the cause."
},
"draft": {
"anyOf": [
{
"type": "object",
"required": [
"author",
"lang",
"said",
"interest",
"names",
"examples"
],
"properties": {
"lang": {
"type": "string",
"pattern": "^[a-z]{2}$",
"description": "The ISO 639-1 language of `said`."
},
"said": {
"type": "string",
"pattern": "\\S",
"maxLength": 1000,
"minLength": 1,
"description": "The reader's words, verbatim; Profile reads them back to that reader."
},
"names": {
"type": "object",
"description": "The names it goes by, per ISO 639-1 language: model-free recall. A name matches whole words, case aside, in a piece's title or teaser, whatever the piece's language; a space or hyphen in it matches a space, a hyphen or nothing, and `*` any letters (a truncation).",
"maxProperties": 12,
"minProperties": 1,
"patternProperties": {
"^[a-z]{2}$": {
"type": "array",
"items": {
"type": "string",
"pattern": "\\S",
"maxLength": 80,
"minLength": 2
},
"maxItems": 20,
"minItems": 1
}
},
"additionalProperties": false
},
"author": {
"enum": [
"reader",
"assistant",
"owner"
],
"type": "string",
"description": "Who wrote this version: the reader, an assistant in conversation, or the owner."
},
"anchors": {
"type": "array",
"items": {
"type": "object",
"required": [
"key",
"use"
],
"properties": {
"key": {
"type": "string",
"pattern": "^(?:country:[A-Z]{2}|medtop:[0-9]{8}|wd:Q[1-9][0-9]{0,9})$",
"description": "country:XX (ISO 3166-1), medtop:NNNNNNNN (an IPTC Media Topic code in the tree) or wd:Qnnn (a Wikidata item), normalised as a magnet's target is."
},
"use": {
"enum": [
"select",
"exclude",
"gate"
],
"type": "string",
"description": "An entity selects or excludes; a code or a country gates or excludes, never selects (0.00 to 0.02 precision as selectors)."
},
"release": {
"anyOf": [
{
"type": "string",
"pattern": "^\\d{4}-\\d\\d-\\d\\d$"
},
{
"type": "null"
}
],
"default": null,
"description": "A Media Topic code's IPTC release; null on a country or an entity."
}
},
"description": "A code, a country or an entity the definition leans on, and how.",
"additionalProperties": false
},
"maxItems": 20,
"description": "Codes, countries and entities, each with its use."
},
"breadth": {
"enum": [
"narrow",
"broad"
],
"type": "string",
"default": "narrow",
"description": "narrow (about it) by default; broad adds adjacent pieces."
},
"counter": {
"type": "array",
"items": {
"type": "object",
"required": [
"item",
"title",
"why"
],
"properties": {
"why": {
"type": "string",
"pattern": "\\S",
"maxLength": 120,
"minLength": 1,
"description": "Why it is in or out, in a few words (\"water\", \"a strike\")."
},
"item": {
"type": "integer",
"minimum": 1,
"description": "The piece's item id. Not checked against the pool, which prunes."
},
"title": {
"type": "string",
"pattern": "\\S",
"maxLength": 400,
"minLength": 1,
"description": "The piece's title as stored, so the definition outlives it."
}
},
"description": "A piece the definition should find (an example) or should not (a counter-example).",
"additionalProperties": false
},
"maxItems": 8,
"description": "Up to 8 pieces the reader does not want, the same shape."
},
"exclude": {
"type": "array",
"items": {
"type": "string",
"pattern": "\\S",
"maxLength": 120,
"minLength": 2
},
"maxItems": 12,
"description": "The wrong senses, named."
},
"include": {
"type": "array",
"items": {
"type": "string",
"pattern": "\\S",
"maxLength": 120,
"minLength": 2
},
"maxItems": 12,
"description": "Each line becomes a facet."
},
"examples": {
"type": "array",
"items": {
"type": "object",
"required": [
"item",
"title",
"why"
],
"properties": {
"why": {
"type": "string",
"pattern": "\\S",
"maxLength": 120,
"minLength": 1,
"description": "Why it is in or out, in a few words (\"water\", \"a strike\")."
},
"item": {
"type": "integer",
"minimum": 1,
"description": "The piece's item id. Not checked against the pool, which prunes."
},
"title": {
"type": "string",
"pattern": "\\S",
"maxLength": 400,
"minLength": 1,
"description": "The piece's title as stored, so the definition outlives it."
}
},
"description": "A piece the definition should find (an example) or should not (a counter-example).",
"additionalProperties": false
},
"maxItems": 8,
"minItems": 3,
"description": "3 to 8 pieces the reader wants, with their titles stored."
},
"interest": {
"type": "string",
"pattern": "\\S",
"maxLength": 600,
"minLength": 1,
"description": "One sentence of what the definition is about: what any future model reads, and a magnet's label."
}
},
"description": "A definition of a reader's own words, one saved version of it (docs/field/own-words.md).",
"additionalProperties": false
},
{
"type": "null"
}
],
"default": null
},
"target": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "What to move: world, country:XX (ISO 3166-1), medtop:NNNNNNNN (an IPTC Media Topic), wd:Qnnn (a Wikidata item), word:<a few words> for a subject no code names, or def:<n> for a saved definition."
},
"preview": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The `confirm` digest a draft's preview answered, to save that very draft."
},
"language": {
"enum": [
"en",
"pl"
],
"type": "string",
"default": "en"
},
"amplitude": {
"enum": [
"away",
"low",
"normal",
"high"
],
"type": "string"
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}my_interests — My interests
Every magnet that draws the reader's edition, theirs over the edition's, with the words they gave, and their credits.
{
"type": "object",
"properties": {
"edition": {
"type": "string",
"default": "world"
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}set_brief — Set the brief
The reader's brief compiled from the record you wrote: who they are, their morning, and lanes, each standing on a target (world, country:XX, medtop:N, wd:Qn), an all_of or any_of of them, or what a piece says; a plain name in place of an id is resolved (one match taken; several: the first taken and one `question`). Answers the record, `resolved`, `read_back` (say it in words), `confirm` for save_brief; or `problem` with a pointer and a fix per error. Nothing is saved.
{
"type": "object",
"required": [
"brief"
],
"properties": {
"brief": {
"type": "string",
"maxLength": 8000,
"minLength": 1,
"description": "The brief: the record in YAML or JSON (the schema at /start/brief.schema.json, the example at /start/brief.example.yaml); a plain name where no id is known is resolved."
},
"language": {
"enum": [
"en",
"pl"
],
"type": "string",
"default": "en"
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}answer_brief — Answer the brief's question
The question set_brief asked, answered: the choice put in the record, which is compiled again.
{
"type": "object",
"required": [
"brief",
"question",
"choice"
],
"properties": {
"brief": {
"type": "string",
"maxLength": 8000,
"minLength": 1,
"description": "The brief: the record in YAML or JSON (the schema at /start/brief.schema.json, the example at /start/brief.example.yaml); a plain name where no id is known is resolved."
},
"choice": {
"type": "string",
"description": "One of its options' `choice` (a target)."
},
"language": {
"enum": [
"en",
"pl"
],
"type": "string",
"default": "en"
},
"question": {
"type": "string",
"description": "The question's `id` (its pointer into the record)."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}rehearse_brief — Rehearse the brief
The mornings of the last days the brief would have given, lane by lane: each line a happening with our title and page and the main it was ranked by; a quiet lane says so. From the pool alone; nothing is saved.
{
"type": "object",
"required": [
"brief"
],
"properties": {
"days": {
"type": "integer",
"default": 7,
"maximum": 14,
"minimum": 1,
"description": "The last mornings read back."
},
"brief": {
"type": "string",
"maxLength": 8000,
"minLength": 1,
"description": "The brief: the record in YAML or JSON (the schema at /start/brief.schema.json, the example at /start/brief.example.yaml); a plain name where no id is known is resolved."
},
"language": {
"enum": [
"en",
"pl"
],
"type": "string",
"default": "en"
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}save_brief — Save the brief
The brief kept, on the reader's yes: their active record, its lanes drawing their own edition from the next morning. Refused when the record changed since its `confirm`.
{
"type": "object",
"required": [
"brief",
"confirm"
],
"properties": {
"brief": {
"type": "string",
"maxLength": 8000,
"minLength": 1,
"description": "The brief: the record in YAML or JSON (the schema at /start/brief.schema.json, the example at /start/brief.example.yaml); a plain name where no id is known is resolved."
},
"confirm": {
"type": "string",
"description": "The `confirm` set_brief or amend_brief gave for this very record."
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}my_brief — My brief
The brief the reader holds, read back (say it in words), with the `confirm` an amendment saves on; or what stands in its place.
{
"type": "object",
"properties": {},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}amend_brief — Amend the brief
The whole brief as amended by one sentence of the reader's, compiled as set_brief does, with `changes` against the one they hold. save_brief with the new `confirm` keeps it.
{
"type": "object",
"required": [
"brief"
],
"properties": {
"brief": {
"type": "string",
"maxLength": 8000,
"minLength": 1,
"description": "The brief: the record in YAML or JSON (the schema at /start/brief.schema.json, the example at /start/brief.example.yaml); a plain name where no id is known is resolved."
},
"language": {
"enum": [
"en",
"pl"
],
"type": "string",
"default": "en"
}
},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}forget_brief — Forget the brief
The reader's brief dropped, only when they asked for that in words: nothing draws their morning but the world's. Their history stays on the site.
{
"type": "object",
"properties": {},
"additionalProperties": false
}{
"type": "object",
"additionalProperties": true
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": true
}Prompts
1 advertised
morning — Stable News morning
Today's edition from Stable News.
- edition
- Provide a value matching the following JSON schema: {"anyOf":[{"type":"string"},{"type":"null"}]}. Encode non-string values as JSON.
Resources
1 advertised
morning_card — Stable News morning card
The morning edition, a list of stories and why each is where it is, drawn as a card.
ui://stable-news/morning-card.html30-day availability
Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.
- Successful checks
- 1 of 1 (100%)
- Average latency
- 1622 ms
- 95th percentile latency
- 1622 ms
Maintenance history
Public check and source-refresh events. Editorial and ownership records remain private.
- · probe · passed · 1622 ms · metadata changed · 13 tool(s), 1 resource(s), 0 resource template(s), 1 prompt(s)
Connect from your client
Each snippet registers the same endpoint; pick the client you use.
Claude Code
claude mcp add --transport http stable-news-mcp https://stablenews.ai/mcp/newsCodex
codex mcp add stable-news-mcp --url https://stablenews.ai/mcp/newsCursor
{
"mcpServers": {
"stable-news-mcp": {
"url": "https://stablenews.ai/mcp/news"
}
}
}Cline
{
"mcpServers": {
"stable-news-mcp": {
"type": "streamableHttp",
"url": "https://stablenews.ai/mcp/news",
"disabled": false
}
}
}VS Code
{
"servers": {
"stable-news-mcp": {
"type": "http",
"url": "https://stablenews.ai/mcp/news"
}
}
}Gemini CLI
gemini mcp add --transport http stable-news-mcp https://stablenews.ai/mcp/newsClaude Desktop
https://stablenews.ai/mcp/newsWindsurf
{
"mcpServers": {
"stable-news-mcp": {
"serverUrl": "https://stablenews.ai/mcp/news"
}
}
}Let your agent find its tools
Find servers like Stable News MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.
Other productivity and knowledge servers
Do you run Stable News MCP?
Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.