{"ok":true,"site":{"host":"agent-native-newsroom.vercel.app","url":"https://agent-native-newsroom.vercel.app/","type":"live","desc":"Agent-native internal newsroom portal: Story Desk, Media Vault and Handoff Engine, operable by humans and browser agents via WebMCP.","tools":[{"name":"find_stories","kind":"answer","impl":"imperative","description":"List newsroom stories with optional filters. Returns id, slug, title, editorial status, desk, author, assignee, word count, media count and whether any attached media has expired rights.","inputSchema":{"type":"object","properties":{"status":{"type":"string","enum":["DRAFT","IN_REVIEW","REVISION_REQUESTED","APPROVED","PUBLISHED"],"description":"Filter by editorial status."},"desk":{"type":"string","description":"Filter by desk, e.g. 'City Hall', 'Business', 'Tech', 'Climate', 'Sports', 'Culture'."},"assignee":{"type":"string","description":"Filter by desk editor assignment (exact name)."},"query":{"type":"string","description":"Free-text search across title, summary, body and author."},"limit":{"type":"integer","minimum":1,"maximum":50,"description":"Max stories to return (default 20)."}}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_story","kind":"answer","impl":"imperative","description":"Get the full record of a single story: headline, standfirst, body, editorial status, assignment, timestamps and all attached media with their rights status.","inputSchema":{"type":"object","properties":{"storyId":{"type":"string","description":"The story id."},"slug":{"type":"string","description":"Alternatively, the story slug (used when storyId is not known)."}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"create_story","kind":"act","impl":"imperative","description":"Create a new story in Draft status. Provide at least a title; summary, body and a publish deadline are recommended so the story can later pass publication validation.","inputSchema":{"type":"object","properties":{"title":{"type":"string","minLength":4,"description":"Headline (4-140 characters)."},"summary":{"type":"string","description":"Standfirst/deck summary (30-300 characters for publish readiness)."},"body":{"type":"string","description":"Full body copy (at least 100 words for publish readiness)."},"desk":{"type":"string","enum":["City Hall","Business","Tech","Climate","Sports","Culture"]},"author":{"type":"string","description":"Byline author name. Defaults to 'Newsroom Staff'."},"assignee":{"type":"string","description":"Desk editor responsible for the story."},"priority":{"type":"string","enum":["LOW","NORMAL","HIGH","URGENT"]},"scheduledFor":{"type":"string","description":"Optional editorial publish deadline (ISO date, e.g. 2025-06-01)."}},"required":["title"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"duplicate_story","kind":"act","impl":"imperative","description":"Pitch a follow-up: clone an existing story as a fresh Draft. Copies headline (suffixed with \"(Follow-up)\"), standfirst, body, desk, byline and priority; media, handoff history and the publish deadline start clean. Returns the new story.","inputSchema":{"type":"object","properties":{"storyId":{"type":"string","description":"The id of the story to clone."}},"required":["storyId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"update_story","kind":"act","impl":"imperative","description":"Update editable fields of a story (title, summary, body, desk, assignee, priority, author, scheduledFor deadline). Published stories are locked. If an APPROVED story's copy (title/summary/body) changes, it is automatically reverted to Draft for re-review. All changes are recorded on the story's editorial timeline.","inputSchema":{"type":"object","properties":{"storyId":{"type":"string","description":"The story id."},"title":{"type":"string","minLength":4},"summary":{"type":"string"},"body":{"type":"string"},"desk":{"type":"string","enum":["City Hall","Business","Tech","Climate","Sports","Culture"]},"assignee":{"type":"string","description":"Desk editor name, or empty string to unassign."},"priority":{"type":"string","enum":["LOW","NORMAL","HIGH","URGENT"]},"author":{"type":"string"},"scheduledFor":{"type":"string","description":"Editorial publish deadline as ISO date (e.g. 2025-06-01), or empty string to clear."}},"required":["storyId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"update_story_status","kind":"act","impl":"imperative","description":"Move a story through the editorial workflow. Allowed transitions: Draft→In Review; In Review→Approved / Revision Requested / Draft; Revision Requested→In Review / Draft; Approved→In Review. Publishing is not allowed here — use prepare_web_handoff + execute_web_handoff.","inputSchema":{"type":"object","properties":{"storyId":{"type":"string"},"status":{"type":"string","enum":["DRAFT","IN_REVIEW","REVISION_REQUESTED","APPROVED","PUBLISHED"]}},"required":["storyId","status"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"approve_story","kind":"act","impl":"imperative","description":"Approve a story that is currently In Review. Only In Review stories can be approved.","inputSchema":{"type":"object","properties":{"storyId":{"type":"string"}},"required":["storyId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"reorder_story","kind":"act","impl":"imperative","description":"Move a story within its current status column's run order (the editing priority inside that stage). Provide beforeStoryId to insert it immediately before another story in the same column, or position 'top'/'bottom'. The column is re-sequenced 1..n and the change is recorded on the story's timeline.","inputSchema":{"type":"object","properties":{"storyId":{"type":"string"},"beforeStoryId":{"type":"string","description":"Insert before this story (must be in the same status column)."},"position":{"type":"string","enum":["top","bottom"],"description":"Alternatively move to the top or bottom of the column (ignored when beforeStoryId is given)."}},"required":["storyId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"search_media","kind":"answer","impl":"imperative","description":"Search the media vault. Filter by free-text query, license type, allowed channel or rights status. rightsStatus \"USABLE\" (default-friendly) returns every asset that can be published today: PERPETUAL or within its license window. Other statuses: VALID (dated license, not near expiry), EXPIRING_SOON, EXPIRED, PERPETUAL.","inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"Free-text search across title, description, photographer and source."},"licenseType":{"type":"string","enum":["Staff Original","Rights-Managed","Editorial Use Only","Royalty-Free","Creative Commons BY"]},"channel":{"type":"string","enum":["web","print","social","broadcast"]},"rightsStatus":{"type":"string","enum":["USABLE","VALID","EXPIRING_SOON","EXPIRED","PERPETUAL"],"description":"USABLE = publishable today (PERPETUAL or VALID)."},"limit":{"type":"integer","minimum":1,"maximum":50}}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_media_metadata","kind":"answer","impl":"imperative","description":"Get full metadata for one media asset: photographer, source, license type and notes, allowed channels, expiry, credit requirements, dimensions and which stories use it.","inputSchema":{"type":"object","properties":{"mediaId":{"type":"string"}},"required":["mediaId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"check_media_rights","kind":"answer","impl":"imperative","description":"Check licensing/rights for web publication. Pass mediaId for a single asset, or storyId to check every asset attached to a story. Reports expired licenses, channel restrictions and missing credits.","inputSchema":{"type":"object","properties":{"mediaId":{"type":"string","description":"Check a single asset."},"storyId":{"type":"string","description":"Check all assets attached to this story."}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"attach_media_to_story","kind":"act","impl":"imperative","description":"Attach a media asset to a story, with optional caption, alt text and primary (lead image) flag. The first attachment becomes primary automatically. Publication validation requires every attachment to carry alt text.","inputSchema":{"type":"object","properties":{"storyId":{"type":"string"},"mediaId":{"type":"string"},"caption":{"type":"string","description":"Editorial caption shown with the image."},"altText":{"type":"string","description":"Text alternative for screen readers, delivered as the payload's alt attribute. Required before handoff."},"isPrimary":{"type":"boolean","description":"Mark as the lead image (demotes other primaries)."}},"required":["storyId","mediaId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"detach_media_from_story","kind":"act","impl":"imperative","description":"Remove a media attachment from a story. If the removed asset was the primary image, the oldest remaining attachment is promoted.","inputSchema":{"type":"object","properties":{"storyId":{"type":"string"},"mediaId":{"type":"string"}},"required":["storyId","mediaId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"replace_story_media","kind":"act","impl":"imperative","description":"Replace an attached media asset in one action (e.g. swap an expired-rights image for a valid one). Detaches the old asset and attaches the new one, preserving caption and lead-image status; alt text resets because the image content changed — pass altText to set it in the same call. Returns the updated story.","inputSchema":{"type":"object","properties":{"storyId":{"type":"string"},"oldMediaId":{"type":"string","description":"Currently attached asset to remove."},"newMediaId":{"type":"string","description":"Replacement asset (must not already be attached)."},"caption":{"type":"string","description":"Optional new caption; omitted keeps the existing caption."},"altText":{"type":"string","description":"Text alternative for the new image; omitted starts without one (handoff will flag it)."}},"required":["storyId","oldMediaId","newMediaId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"register_media_asset","kind":"act","impl":"imperative","description":"Register a new media asset in the vault from an external image URL (agent-supplied or wire-service imagery). The image is referenced, not downloaded. Provide full licensing metadata — license type, allowed channels, expiry and credit line — so the Handoff Engine can gate publication on rights. Returns the created asset.","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"http(s) URL of the image."},"title":{"type":"string","minLength":3,"description":"Vault title for the asset."},"photographer":{"type":"string","description":"Photographer or originating agency."},"source":{"type":"string","description":"Wire service / source name. Defaults to 'External wire'."},"description":{"type":"string","description":"What the image shows."},"licenseType":{"type":"string","enum":["Staff Original","Rights-Managed","Editorial Use Only","Royalty-Free","Creative Commons BY"],"description":"Defaults to 'Rights-Managed'."},"licenseNotes":{"type":"string","description":"Free-form licensing notes/restrictions."},"allowedChannels":{"type":"array","items":{"type":"string","enum":["web","print","social","broadcast"]},"description":"Channels the license permits. Defaults to ['web']."},"expiresAt":{"type":"string","description":"License expiry as ISO date (e.g. 2027-01-31); omit for perpetual rights."},"creditRequired":{"type":"boolean","description":"Whether attribution is mandatory (default true)."},"creditLine":{"type":"string","description":"The required credit line, e.g. 'Photo: K. Osei / Meridian'."},"width":{"type":"integer","description":"Image width in px, if known."},"height":{"type":"integer","description":"Image height in px, if known."}},"required":["url","title","photographer"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"update_story_media","kind":"act","impl":"imperative","description":"Update an attachment's editorial fields on a story: caption, alt text (required for publication) and the lead-image flag. Only sent fields are changed; a caption/alt-only update never touches the lead flag.","inputSchema":{"type":"object","properties":{"storyId":{"type":"string"},"mediaId":{"type":"string","description":"The attached media asset id."},"caption":{"type":"string","description":"Editorial caption; empty string clears it."},"altText":{"type":"string","description":"Text alternative for screen readers; empty string clears it. Publication validation requires one per attachment."},"isPrimary":{"type":"boolean","description":"Explicitly set or unset the lead-image flag."}},"required":["storyId","mediaId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"suggest_alt_text","kind":"answer","impl":"imperative","description":"Get a deterministic alt-text suggestion for a story attachment (derived from the attachment caption, the asset description or the asset title, first sentence, max 140 chars). Use it before update_story_media to write a screen-reader-friendly alt — the same routine the editor-facing 'Suggest' button uses.","inputSchema":{"type":"object","properties":{"storyId":{"type":"string"},"mediaId":{"type":"string","description":"The attached media asset id."}},"required":["storyId","mediaId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"renew_media_licenses","kind":"act","impl":"imperative","description":"Extend the license window of one or more dated media assets in a single action (bulk renewal). Sets a new expiry date for every given asset and records an optional renewal note in each asset's license notes. Typical use: renew every EXPIRING_SOON or EXPIRED asset found via search_media before a handoff.","inputSchema":{"type":"object","properties":{"mediaIds":{"type":"array","items":{"type":"string"},"description":"IDs of the media assets to renew."},"expiresAt":{"type":"string","description":"New license expiry date (ISO date string), e.g. '2027-09-02'."},"note":{"type":"string","description":"Optional renewal note appended to each asset's license notes."}},"required":["mediaIds","expiresAt"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_story_history","kind":"answer","impl":"imperative","description":"Get the editorial timeline (audit trail) of a story: creation, status changes, edits, media attachments/replacements, deadline changes and handoffs, each with the actor and timestamp.","inputSchema":{"type":"object","properties":{"storyId":{"type":"string"}},"required":["storyId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"validate_publication","kind":"act","impl":"imperative","description":"Run full pre-publication validation for a story: approved status, editor assigned, headline/standfirst/body quality, media attached with primary set, licenses valid, web channel allowed, credits present and alt text on every attachment. Returns a checklist with pass/fail per requirement.","inputSchema":{"type":"object","properties":{"storyId":{"type":"string"}},"required":["storyId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"prepare_web_handoff","kind":"act","impl":"imperative","description":"Generate the web publishing payload for a validated, approved story. Fails with the validation checklist when the story is not ready. Returns the payload plus a field-level diff against the previous prepared-but-undelivered draft (server-side memory), so callers can see exactly what a re-preparation changed. Review the payload before executing the handoff.","inputSchema":{"type":"object","properties":{"storyId":{"type":"string"},"requestedBy":{"type":"string","description":"Identifier of the requester, e.g. 'editor-agent'."}},"required":["storyId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"execute_web_handoff","kind":"act","impl":"imperative","description":"Perform the simulated web handoff: re-validates the story, delivers the payload to the (simulated) web CMS and marks the story Published. Blocked if validation fails.","inputSchema":{"type":"object","properties":{"storyId":{"type":"string"},"requestedBy":{"type":"string","description":"Identifier of the requester, e.g. 'editor-agent'."}},"required":["storyId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"}],"category":"Media & Personal","favicon":"/favicons/agent-native-newsroom.vercel.app.svg","apiSurface":"spec","toolCount":22}}