Stories
Reference for the 6 Stories MCP tools: list_stories, get_story, get_story_enrichment, dismiss_story_element, restore_story_element, add_story_photos.
list_stories
List stories for the org, both those minted from an approved pitch and those minted from the newsroom system (NRCS), newest-updated first (paginated, optionally filtered by title, newsdesk, enrichment status or source). Stories the NRCS dropped (archived or deleted there) are left out. Returns { items, nextCursor }. Pass cursor from a prior nextCursor to fetch the next page. Each story carries source (pitch or nrcs), origin (engine, manual, or the NRCS vendor), url (a link to it in the web app), newsdeskName, and orgName alongside the existing raw newsdeskId; an NRCS story has a null newsdeskId and newsdeskName. enrichmentAttempts counts transient-failure retries, not total attempts made -- 0 means the run succeeded (or hasn't started) without needing one.
read-only · idempotent · closed-world
limitinteger— Items per page (1–100, default 25)cursorstring— Opaque cursor from a prior nextCursornewsdeskIdstring— Filter to stories for this newsdesktitlestring— Filter to stories whose title contains this text (case-insensitive)enrichmentStatusstring— one ofpending,running,enriched,failed— Filter by claim-loop enrichment statussourcestring— one ofpitch,nrcs— Filter by where the story was minted: pitch (an approved pitch) or nrcs (the newsroom system)
get_story
Get a story by ID — the full detail (sources, meaning, factCheck, claims, entities, timeline, key quotes, media, and NRCS push history) of a story minted from a pitch or from the NRCS. nrcsRecords lists the newsroom-system records behind it (vendor, connection, entity type, state, assignees, body text, externalUrl, status), and nrcsDropped says why the NRCS dropped it (archived or deleted), or null while it is live. An element with dismissed: true was rejected by an editor: do not use it. This covers a quote, an archive asset in mamAssets, a post in ugcPosts and a picture in media, which all stay in the story flagged rather than removed. A dismissal names its element by its own fields: for a quote, original.text; for an archive asset, mamConfigId and itemId; for a post, postUrl; for media, dismissKey (never assetUrl, which is signed or rewritten for this read). Carries url (a link to it in the web app), newsdeskName, and orgName alongside the existing raw newsdeskId. sources omits any additional-origin source that was found by research but never actually fetched -- it was never available to the enrichment run either. enrichmentAttempts counts transient-failure retries, not total attempts made -- 0 means the run succeeded (or hasn't started) without needing one.
read-only · idempotent · closed-world
idstring(required) — Story identifier
get_story_enrichment
Get a story's claim-loop enrichment progress: { run, logs, logsCursor, logsTruncated }. run is null when the story has never been claimed yet (still "pending" -- the web app displays this state as "Queued"). logs are oldest-first. Pass logsCursor from a prior call to fetch only log rows added since, for polling.
read-only · idempotent · closed-world
idstring(required) — Story identifierlogsCursorstring— Opaque cursor from a prior call's logsCursor; returns only log rows added since
dismiss_story_element
Dismiss one element of a story -- a key quote, an archive asset, a UGC post or a picture -- so every output stops using it and the web app collapses it. Dismiss only what the user asked you to dismiss: a dismissal is an editor's rejection, recorded in the audit log under their name. kind says what you are naming, and each kind takes its own fields, all read on get_story: quote takes original (a quote's original.text in quotes); mam_asset takes mamConfigId and itemId (an entry of mamAssets); ugc_post takes postUrl (an entry of ugcPosts); media takes dismissKey (an entry of media, never its assetUrl). A missing field, or one the kind does not take, is an input error. Dismissing what is already dismissed changes nothing. Undo it with restore_story_element or the Undo on the story page. Needs a user credential, so an interactive MCP connection: a service-key (static API key) connection is refused. Returns { storyId, kind, dismissed }, dismissed being the element's state after the call; read get_story for the whole story.
additive · idempotent · closed-world
storyIdstring(required) — Story identifierkindstring(required) — one ofquote,mam_asset,ugc_post,media— Which kind of element to nameoriginalstring— kind quote: the quote's original.text, as get_story returns it in quotesmamConfigIdstring— kind mam_asset: the asset's mamConfigId, as get_story returns it in mamAssetsitemIdstring— kind mam_asset: the asset's itemId, as get_story returns it in mamAssetspostUrlstring— kind ugc_post: the post's postUrl, as get_story returns it in ugcPostsdismissKeystring— kind media: the picture's dismissKey, as get_story returns it in media (never its assetUrl)
restore_story_element
Undo dismiss_story_element: bring a dismissed story element -- a key quote, an archive asset, a UGC post or a picture -- back, so outputs may use it again. Restore only what the user asked you to restore. Name the element as dismiss_story_element does: quote takes original; mam_asset takes mamConfigId and itemId; ugc_post takes postUrl; media takes dismissKey, all read on get_story where the element carries dismissed: true. A missing field, or one the kind does not take, is an input error. Restoring an element that is not dismissed changes nothing. Needs a user credential, so an interactive MCP connection: a service-key (static API key) connection is refused. Returns { storyId, kind, dismissed }, dismissed being the element's state after the call.
additive · idempotent · closed-world
storyIdstring(required) — Story identifierkindstring(required) — one ofquote,mam_asset,ugc_post,media— Which kind of element to nameoriginalstring— kind quote: the quote's original.text, as get_story returns it in quotesmamConfigIdstring— kind mam_asset: the asset's mamConfigId, as get_story returns it in mamAssetsitemIdstring— kind mam_asset: the asset's itemId, as get_story returns it in mamAssetspostUrlstring— kind ugc_post: the post's postUrl, as get_story returns it in ugcPostsdismissKeystring— kind media: the picture's dismissKey, as get_story returns it in media (never its assetUrl)
add_story_photos
Attach one to five photos to a story by URL, so an agent that holds a link (a press office's handout, a photo an editor pasted) can supply a picture without moving bytes. The server fetches each https URL (public hosts only, a JPEG, PNG or WebP of at most 20 MiB), stores it as the story's own photo, and attaches it; every post on the story then offers it as a card photo. Photos are fetched one after another and each ends in its own result, in the order given: { url, attached } with the stored photo, { url, refused } with the reason (not public https, not reachable, not found, too large, not an image, unreadable size, or the org's storage is full), { url, retry } with advice to send that photo again in another call (every image slot on the server was busy, or the call ran out of time: no new photo starts after 60 seconds), or { url, failed: "internal" } for a fault on Nuvelics' side. One photo's refusal never stops the others, so photos already attached are always reported. The call answers { storyId, url, results } with url a link to the story in the web app. Nothing dedupes a URL: sending an attached photo again attaches it again. credit and caption are optional (a blank one is treated as absent; credit at most 200 characters, caption at most 500). Requires story:write and the story to exist, checked once before any fetch; either failing fails the whole call. A photo can be removed only from the web app or the CLI.
additive · open-world
storyIdstring(required) — Story identifierphotosarray(required) — One to five photos to attach, in order