Koskamo

Storyflo MCP

An MCP server providing agent-native tools for discovering and consuming curated audio news, including search, digest, and subscription features. It offers access to a public Declassified library of government audio and market-linked signals, with premium briefings available via x402 payment.

Endpoint and access

OAuth sign-in: the first time you connect, your client opens the vendor's own authorization prompt in a browser.

Storyflo MCP logo, by StoryfloCommunity listingStreamable HTTPOAuth sign-inEndpoint checked 2026-11-06Published by Storyflo
MCP endpoint (Streamable HTTP)
https://api.storyflo.com/mcp/v1
Vendor documentation

What its tools do

37 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.

37 of 37 have a description · 37 of 37 declare behavior hints · 18 of 32 with parameters document them all

Checks and signals

Each line is separate evidence, not a trust score.

  • Passed Endpoint answered the live check ·
  • Availability 1 of 1 checks passed in 30 days

What you can do with it

  • Search and retrieve articles with audio URLs
  • Access public Declassified government audio library
  • Subscribe to topics and manage private feeds
  • Get market-linked stories and crypto signals

Source and maintenance

Community listingRegistry 1.2.0
Maintenance checked

Protocol and capabilities

Server
Storyflo 1.3.0
MCP protocol negotiated in check
2025-11-25
Tools
37 advertised
Resources
0 advertised
Resource templates
Sign-in required
Prompts
Not advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": false
  },
  "resources": {
    "listChanged": false
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

Storyflo provides curated audio-news plus a market-aware news signal. AUTH: most tools need an OAuth bearer token (scope articles:read). A call without one returns 401 with a WWW-Authenticate header pointing at https://api.storyflo.com/.well-known/oauth-protected-resource/mcp/v1 — MCP clients that support OAuth will complete the flow automatically. Requires OAuth: digest, get_article, get_audio_url, get_crypto_market_link, get_market_linked_stories, get_mcp_usage_self, list_subscriptions, search_articles, search_unified, subscribe_topic. Everything else below is callable with no credential at all. Premium tool: get_vertical_briefing — settles in USDC on Base via x402. Declassified library (public, no auth): search_declassified, get_declassified_case, digest_declassified, subscribe_declassified_topic — narrated cases drawn from FBI/CIA/NSA/NASA/DOJ/AARO/war.gov releases. Discovery surface (public, no auth): get_trending_topics, get_personas, get_vertical_landscape, list_podcasts — surface what's hot on storyflo + pick a host voice + one-shot vertical context for onboarding a listener + the full catalog of audio shows (Theo / Mason / Jessica / Chloe / Brock / Wit + Declassified). Partner integration (public, no auth): register_embedder (returns onboarding URL, does NOT send email or create a row), get_embedder_manifest, get_embedder_network_manifest, quote_partnership — explore tiers + creative formats + payout rails before opening a partnership thread. get_market_linked_stories pairs stories with event contracts on Kalshi (a CFTC-regulated designated contract market); informational market data only, not investment advice. get_crypto_market_link returns Storyflo's markets-partner Kraken affiliate URL for crypto-relevant stories — editorial linkout, not a trading recommendation; not investment advice.

Tools

37 advertised

search_articles — Search Storyflo articles
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Search Storyflo's article corpus. Returns slug, title, publisher, vertical, snippet, audio_url, and listen_seconds for each match. Use vertical to scope (tech / finance / science / media / sports / culture).

search_articles input schema
{
  "type": "object",
  "properties": {
    "limit": {
      "type": "integer",
      "default": 20,
      "maximum": 100,
      "minimum": 1
    },
    "query": {
      "type": "string",
      "description": "Search query"
    },
    "vertical": {
      "enum": [
        "tech",
        "finance",
        "science",
        "media",
        "sports",
        "culture"
      ],
      "type": "string"
    }
  }
}
search_articles annotations
{
  "title": "Search Storyflo articles",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_article — Get article
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Fetch the full record for an article by slug, including body_text + audio_url.

get_article input schema
{
  "type": "object",
  "required": [
    "slug"
  ],
  "properties": {
    "slug": {
      "type": "string"
    }
  }
}
get_article annotations
{
  "title": "Get article",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_audio_url — Get audio URL
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Resolve the playable audio URL for an article. Returns a stitched-with-ad URL on free tier or the bare audio for plus/pro.

get_audio_url input schema
{
  "type": "object",
  "required": [
    "slug"
  ],
  "properties": {
    "slug": {
      "type": "string"
    }
  }
}
get_audio_url annotations
{
  "title": "Get audio URL",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
subscribe_topic — Subscribe to topic feed
Advertised by the server during the last successful anonymous check.

Mint or update the human's personal Storyflo podcast feed. Pass 1–6 vertical slugs from `tech`, `finance`, `science`, `media`, `sports`, `culture`. The server creates a private RSS feed scoped to those verticals — or updates the existing feed in place if the listener already has one. Returns the RSS URL the listener can paste into Spotify, Apple Podcasts, Pocket Casts, or any podcast client. Behavior • Persistent server-side side-effect — a `ListenerSubscription` row is created or updated. The returned RSS URL stays stable across calls for the same listener (the listener doesn't need to re-paste it). • Idempotent on identical input — calling twice with the same verticals leaves state unchanged. • REPLACES on different input — calling with a different verticals set OVERWRITES the previous selection rather than adding to it. Use this to switch a listener's feed; do NOT call to add verticals incrementally (read the current set via `list_subscriptions` first and pass the union if you want additive behavior). • Single feed per listener — call `list_subscriptions` first to avoid clobbering an existing feed the listener explicitly chose. When to use Use after the agent has been asked to set up audio news for the human across a defined set of topics. Do NOT use to FETCH articles or audio — that's `search_articles` + `get_audio_url`.

subscribe_topic input schema
{
  "type": "object",
  "required": [
    "verticals"
  ],
  "properties": {
    "verticals": {
      "type": "array",
      "items": {
        "enum": [
          "tech",
          "finance",
          "science",
          "media",
          "sports",
          "culture"
        ],
        "type": "string"
      },
      "maxItems": 6,
      "minItems": 1,
      "description": "1–6 vertical slugs the feed should cover. Replaces (not appends) the listener's current selection.",
      "uniqueItems": true
    }
  }
}
subscribe_topic annotations
{
  "title": "Subscribe to topic feed",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
list_subscriptions — List active subscriptions
Advertised by the server during the last successful anonymous check.
Advertised read-only

Return the listener feed(s) this agent has minted on the human's behalf.

list_subscriptions input schema
{
  "type": "object",
  "properties": {}
}
list_subscriptions annotations
{
  "title": "List active subscriptions",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_vertical_briefing — Get per-vertical premium briefing
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Fetch a stitched audio briefing of the top-25 trending articles in a single vertical from the last 24h. Premium — settles in USDC on Base via x402. Vertical must be one of the canonical 7 buckets: tech, finance, news, science, health, young_moms, yoga. First call without an X-Payment header returns the x402 challenge; sign + retry.

get_vertical_briefing input schema
{
  "type": "object",
  "required": [
    "vertical"
  ],
  "properties": {
    "vertical": {
      "enum": [
        "tech",
        "finance",
        "news",
        "science",
        "health",
        "young_moms",
        "yoga"
      ],
      "type": "string"
    }
  }
}
get_vertical_briefing annotations
{
  "title": "Get per-vertical premium briefing",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_market_linked_stories — Get stories with active matched event-contract markets
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Storyflo stories that match an actively traded event contract on Kalshi (a CFTC-regulated exchange). Each item carries qualitative signal tags (high_velocity, genuine_uncertainty) plus a link-out to Kalshi's own page where the live market data lives. Editorial sourcing surface, not market-data redistribution: Storyflo never returns raw prices, market-implied probabilities, volumes, or open interest in this payload. Use this when the agent needs to know which Storyflo stories are about news themes that have an actively traded event contract — e.g. World Cup matches, political mention contracts, corporate events. Filter by story vertical, Kalshi category (Politics, Economics, Companies, Science and Technology, Sports), or by signal tag.

get_market_linked_stories input schema
{
  "type": "object",
  "properties": {
    "limit": {
      "type": "integer",
      "default": 10,
      "maximum": 50,
      "minimum": 1
    },
    "signal": {
      "enum": [
        "active",
        "high_velocity",
        "genuine_uncertainty"
      ],
      "type": "string",
      "description": "Filter by qualitative signal tag. high_velocity = the matched market is repricing meaningfully in the last 24h; genuine_uncertainty = the market sits in the 40–60% band where it itself is uncertain."
    },
    "category": {
      "type": "string",
      "description": "Filter by Kalshi event category (e.g. Politics, Economics, Companies, Sports)"
    },
    "vertical": {
      "type": "string",
      "description": "Filter by story vertical (e.g. news, finance, tech, crypto)"
    }
  }
}
get_market_linked_stories annotations
{
  "title": "Get stories with active matched event-contract markets",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_crypto_market_link — Get crypto market exposure link (Kraken affiliate)
Advertised by the server during the last successful anonymous check.
Advertised read-only

Return Storyflo's markets-partner Kraken affiliate URL for a given crypto asset (BTC, ETH, etc). Editorial linkout, not a trading prompt: the URL points at Kraken's public asset page so a listener who wants exposure can reach a regulated venue without leaving the brief context. Markets-as-INPUT posture (counsel-cleared) — Storyflo never quotes prices, never recommends positions, and never frames exposure as risk-free. Behavior - Read-only. No persistent server state. - Idempotent — same (asset, embedder_slug) returns the same URL. - Fail-closed — when KRAKEN_AFFILIATE_ENABLED is off OR the partner base URL is unset, the call returns an error structure rather than a half-formed URL. - Attribution-aware — pass embedder_slug to credit the embedding publisher in the affiliate ?ref parameter; default falls back to ?ref=storyflo so the link is always trackable. When to use Surface the link in show-notes copy or in MCP-client renderings of a crypto-relevant story. DO NOT inline the URL into spoken audio narration without the host-read line that frames it as an editorial signal.

get_crypto_market_link input schema
{
  "type": "object",
  "required": [
    "asset"
  ],
  "properties": {
    "asset": {
      "type": "string",
      "description": "Primary crypto asset symbol — BTC, ETH, SOL, USDC, etc. Case-insensitive; upper-cased before being embedded in the URL."
    },
    "embedder_slug": {
      "type": "string",
      "description": "Optional embedder attribution slug. When set, the affiliate URL carries ?ref=<slug>; omit to default to ?ref=storyflo."
    }
  }
}
get_crypto_market_link annotations
{
  "title": "Get crypto market exposure link (Kraken affiliate)",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
digest — Build a daily digest
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Aggregate the top-N articles across selected verticals for the requested window. Heaviest action — counts more against the per-agent rate limit. Use this for 'read me today's tech news' style prompts.

digest input schema
{
  "type": "object",
  "properties": {
    "limit": {
      "type": "integer",
      "default": 5,
      "maximum": 20,
      "minimum": 1
    },
    "window": {
      "enum": [
        "24h",
        "7d",
        "30d"
      ],
      "type": "string",
      "default": "24h"
    },
    "verticals": {
      "type": "array",
      "items": {
        "enum": [
          "tech",
          "finance",
          "science",
          "media",
          "sports",
          "culture"
        ],
        "type": "string"
      }
    }
  }
}
digest annotations
{
  "title": "Build a daily digest",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
publisher_connect_folder — Connect a recordings folder
Advertised by the server during the last successful anonymous check.

Connect a Google Drive folder of recordings so storyflo can match them to episodes automatically — the alternative to uploading a back catalogue file by file. Call with NO folder argument first to get the setup instructions, including the address to share the folder with. Then call again with folder=<the Drive URL>. Recording the connection moves no audio; the scan happens afterwards.

publisher_connect_folder input schema
{
  "type": "object",
  "required": [
    "tenant_slug",
    "token"
  ],
  "properties": {
    "token": {
      "type": "string",
      "description": "Your publisher access token."
    },
    "folder": {
      "type": "string",
      "description": "Google Drive folder URL or id. Omit to get setup instructions."
    },
    "tenant_slug": {
      "type": "string",
      "description": "Your publisher slug on storyflo."
    }
  }
}
publisher_connect_folder annotations
{
  "title": "Connect a recordings folder",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
publisher_folder_status — Connected folder status
Advertised by the server during the last successful anonymous check.
Advertised read-only

What the connected folder has produced: files seen, files matched and attached, and — most usefully — the files storyflo could read but would NOT auto-attach because the filename did not clearly identify an episode. Those are listed with the reason so they can be renamed and picked up on the next scan.

publisher_folder_status input schema
{
  "type": "object",
  "required": [
    "tenant_slug",
    "token"
  ],
  "properties": {
    "token": {
      "type": "string",
      "description": "Your publisher access token."
    },
    "tenant_slug": {
      "type": "string",
      "description": "Your publisher slug on storyflo."
    }
  }
}
publisher_folder_status annotations
{
  "title": "Connected folder status",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
publisher_upload_audio — Upload source audio
Advertised by the server during the last successful anonymous check.

Get a one-time upload URL for an episode's source audio — your own recording (StreamYard, Riverside, Zoom, a local file). Use this when an episode shows as 'awaiting': storyflo knows it exists but has no audio for it. Returns a presigned PUT URL plus a ready-to-paste curl command. Nothing changes in storyflo until you upload and then call publisher_attach_audio — this tool alone moves no bytes and mutates nothing.

publisher_upload_audio input schema
{
  "type": "object",
  "required": [
    "tenant_slug",
    "token"
  ],
  "properties": {
    "token": {
      "type": "string",
      "description": "Your publisher access token."
    },
    "tenant_slug": {
      "type": "string",
      "description": "Your publisher slug on storyflo."
    },
    "content_type": {
      "type": "string",
      "default": "audio/mpeg",
      "description": "Audio MIME type, e.g. audio/mpeg for mp3."
    },
    "episode_slug": {
      "type": "string",
      "description": "Episode this audio is for."
    }
  }
}
publisher_upload_audio annotations
{
  "title": "Upload source audio",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": false
}
publisher_attach_audio — Attach uploaded audio to an episode
Advertised by the server during the last successful anonymous check.

Confirm a finished upload and mark that episode live. Verifies the file really landed in storage before changing anything, then points the episode at it so it appears in your RSS feed on the next build. Attaches ONE upload to ONE episode you own.

publisher_attach_audio input schema
{
  "type": "object",
  "required": [
    "tenant_slug",
    "token",
    "key",
    "episode_slug"
  ],
  "properties": {
    "key": {
      "type": "string",
      "description": "The key returned by publisher_upload_audio."
    },
    "token": {
      "type": "string",
      "description": "Your publisher access token."
    },
    "tenant_slug": {
      "type": "string",
      "description": "Your publisher slug on storyflo."
    },
    "episode_slug": {
      "type": "string",
      "description": "Episode to attach it to."
    }
  }
}
publisher_attach_audio annotations
{
  "title": "Attach uploaded audio",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
fm_book_status — My desk book
Advertised by the server during the last successful anonymous check.
Advertised read-only

A signalflo fund manager's own book: which calls are open, how many have closed, and the deep links to the desk and dashboard. Use this first when a manager asks what is on their book right now.

fm_book_status input schema
{
  "type": "object",
  "required": [
    "tenant_slug",
    "access_token"
  ],
  "properties": {
    "tenant_slug": {
      "type": "string",
      "description": "Your desk slug on storyflo."
    },
    "access_token": {
      "type": "string",
      "description": "Your access token — the same one your storyflo dashboard uses."
    }
  }
}
fm_book_status annotations
{
  "title": "My desk book",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
fm_open_position — Open a position
Advertised by the server during the last successful anonymous check.

Record a new call on your book: the event, which way you lean, and why. Idempotent — opening a call you already hold repositions it instead of creating a duplicate, so an agent may safely re-run its loop. Lean and rationale must be QUALITATIVE: a percentage, odds or implied probability is refused, because a number attached to a market view reads as investment advice.

fm_open_position input schema
{
  "type": "object",
  "required": [
    "tenant_slug",
    "access_token",
    "event"
  ],
  "properties": {
    "lean": {
      "type": "string",
      "description": "Which way you lean, in words. No numbers."
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "event": {
      "type": "string",
      "description": "What the call is about."
    },
    "category": {
      "type": "string"
    },
    "rationale": {
      "type": "string",
      "description": "Why, in words. No odds or percentages."
    },
    "story_url": {
      "type": "string"
    },
    "venue_url": {
      "type": "string"
    },
    "story_title": {
      "type": "string"
    },
    "tenant_slug": {
      "type": "string"
    },
    "access_token": {
      "type": "string"
    },
    "aqua_position_ref": {
      "type": "string",
      "description": "Optional. The 1inch Aqua position this call is about — an https 1inch/Aqua URL or a position id (0x… or digits). Pair with the 1inch Aqua MCP: open the position there (you sign), then record the call here referencing it. A REFERENCE only — never price, range or fee, and never prose."
    }
  }
}
fm_open_position annotations
{
  "title": "Open a position",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
fm_reposition — Reposition a call
Advertised by the server during the last successful anonymous check.

Update your view on an open call as the signal evolves. Same qualitative rule as opening one.

fm_reposition input schema
{
  "type": "object",
  "required": [
    "tenant_slug",
    "access_token",
    "position_key"
  ],
  "properties": {
    "lean": {
      "type": "string"
    },
    "rationale": {
      "type": "string"
    },
    "tenant_slug": {
      "type": "string"
    },
    "access_token": {
      "type": "string"
    },
    "position_key": {
      "type": "string",
      "description": "From fm_book_status or fm_open_position."
    },
    "aqua_position_ref": {
      "type": "string",
      "description": "Optional. The 1inch Aqua position this call is about — an https 1inch/Aqua URL or a position id (0x… or digits). Pair with the 1inch Aqua MCP: open the position there (you sign), then record the call here referencing it. A REFERENCE only — never price, range or fee, and never prose."
    }
  }
}
fm_reposition annotations
{
  "title": "Reposition a call",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": false
}
fm_close_position — Close a position
Advertised by the server during the last successful anonymous check.

Close a call when the divergence resolves or goes stale. The position stays on the book as closed rather than being deleted.

fm_close_position input schema
{
  "type": "object",
  "required": [
    "tenant_slug",
    "access_token",
    "position_key"
  ],
  "properties": {
    "note": {
      "type": "string",
      "description": "Optional closing note, in words."
    },
    "tenant_slug": {
      "type": "string"
    },
    "access_token": {
      "type": "string"
    },
    "position_key": {
      "type": "string"
    }
  }
}
fm_close_position annotations
{
  "title": "Close a position",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
publisher_status — My storyflo status
Advertised by the server during the last successful anonymous check.
Advertised read-only

Where a publisher stands right now: their RSS feed URL (the one to submit to Apple Podcasts and Spotify), how many episodes storyflo holds, how many already have finished audio, and how many are still awaiting source audio. Use this for 'what is my feed URL', 'is anything stuck', or as the first call when a publisher asks how things are going.

publisher_status input schema
{
  "type": "object",
  "required": [
    "tenant_slug",
    "token"
  ],
  "properties": {
    "token": {
      "type": "string",
      "description": "Your publisher access token — the same one the dashboard uses. Rotatable at POST /v1/publisher/{slug}/access-token/rotate."
    },
    "tenant_slug": {
      "type": "string",
      "description": "Your publisher slug on storyflo."
    }
  }
}
publisher_status annotations
{
  "title": "My storyflo status",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
publisher_episodes — My episodes
Advertised by the server during the last successful anonymous check.
Advertised read-only

List a publisher's episodes newest-first with their real state: 'live' (has finished audio and appears in the RSS feed) or 'awaiting' (storyflo knows the episode exists but has no finished audio yet). Filter with status=live or status=awaiting to answer 'what is still pending?'.

publisher_episodes input schema
{
  "type": "object",
  "required": [
    "tenant_slug",
    "token"
  ],
  "properties": {
    "limit": {
      "type": "integer",
      "default": 20,
      "maximum": 100,
      "minimum": 1
    },
    "token": {
      "type": "string",
      "description": "Your publisher access token — the same one the dashboard uses. Rotatable at POST /v1/publisher/{slug}/access-token/rotate."
    },
    "status": {
      "enum": [
        "live",
        "awaiting"
      ],
      "type": "string"
    },
    "tenant_slug": {
      "type": "string",
      "description": "Your publisher slug on storyflo."
    }
  }
}
publisher_episodes annotations
{
  "title": "My episodes",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
publisher_stats — My listening stats
Advertised by the server during the last successful anonymous check.
Advertised read-only

Plays over a window (default 30 days, max 365) plus the episodes driving them. Answers 'how did last month go' and 'which episode is working'. Zero plays on a new feed is normal — directories take days to index a fresh RSS URL.

publisher_stats input schema
{
  "type": "object",
  "required": [
    "tenant_slug",
    "token"
  ],
  "properties": {
    "days": {
      "type": "integer",
      "default": 30,
      "maximum": 365,
      "minimum": 1
    },
    "token": {
      "type": "string",
      "description": "Your publisher access token — the same one the dashboard uses. Rotatable at POST /v1/publisher/{slug}/access-token/rotate."
    },
    "tenant_slug": {
      "type": "string",
      "description": "Your publisher slug on storyflo."
    }
  }
}
publisher_stats annotations
{
  "title": "My listening stats",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
search_unified — Unified search (news + declassified + signals)
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Search ALL of Storyflo in one call and get results back as separate per-corpus buckets: `news` (the narrated article archive), `declassified` (government-document cases), and `signals` (Atlas's book of positions off the Divergence Index). Use this when you do not already know which corpus holds the answer, or when a topic spans several — e.g. a macro question with both coverage and a live position. Results are ranked WITHIN each corpus and never blended, so a large corpus cannot drown a small one. `profile=desk` leads with signals (news/declassified as supporting evidence); `profile=publisher` leads with news and declassified carrying attribution for citation. Signals are qualitative only — no raw market odds, not investment advice.

search_unified input schema
{
  "type": "object",
  "required": [
    "query"
  ],
  "properties": {
    "limit": {
      "type": "integer",
      "default": 10,
      "maximum": 50,
      "minimum": 1,
      "description": "Max results PER CORPUS."
    },
    "query": {
      "type": "string",
      "description": "What to search for, across every corpus."
    },
    "corpora": {
      "type": "string",
      "description": "Comma-separated subset: news, declassified, signals. Omit for all three."
    },
    "profile": {
      "enum": [
        "desk",
        "publisher"
      ],
      "type": "string",
      "description": "Ranking emphasis. Same buckets either way; only order and enrichment differ."
    },
    "vertical": {
      "type": "string"
    }
  }
}
search_unified annotations
{
  "title": "Unified search",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
search_declassified — Search Declassified library
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Search Storyflo's Declassified archive — narrated cases drawn from FBI, CIA, NSA, NASA, DOJ, AARO, war.gov and other publicly-released government documents. Substring match across case title + synopsis. Use when the agent needs to find a Declassified case matching a topic (e.g. 'UAP', 'JFK', 'COINTELPRO', 'Roswell') before fetching the full case via `get_declassified_case` or handing the audio_url to a player. Public — no auth required.

search_declassified input schema
{
  "type": "object",
  "required": [
    "query"
  ],
  "properties": {
    "limit": {
      "type": "integer",
      "default": 10,
      "maximum": 50,
      "minimum": 1
    },
    "query": {
      "type": "string",
      "description": "Substring matched against case title + synopsis."
    }
  }
}
search_declassified annotations
{
  "title": "Search Declassified library",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_declassified_case — Get Declassified case
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Fetch the full record for a Declassified case by slug. Returns title, summary, transcript_excerpt, episode_date, duration_sec, agency, audio_url, source_doc_url, and up to 5 related cases. Use after `search_declassified` when the agent needs the full case body to summarize, narrate, or hand off audio playback. Public — no auth required.

get_declassified_case input schema
{
  "type": "object",
  "required": [
    "slug"
  ],
  "properties": {
    "slug": {
      "type": "string",
      "description": "Case slug as returned by `search_declassified`."
    }
  }
}
get_declassified_case annotations
{
  "title": "Get Declassified case",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
digest_declassified — Recent Declassified cases
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Return the most-recently-published Declassified cases over a rolling window. Use for 'what's new in Declassified this week' style prompts. window=today (~24h) | week (default) | month. Public — no auth required.

digest_declassified input schema
{
  "type": "object",
  "properties": {
    "limit": {
      "type": "integer",
      "default": 10,
      "maximum": 50,
      "minimum": 1
    },
    "window": {
      "enum": [
        "today",
        "week",
        "month"
      ],
      "type": "string",
      "default": "week"
    }
  }
}
digest_declassified annotations
{
  "title": "Recent Declassified cases",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
subscribe_declassified_topic — Subscribe to Declassified topic
Advertised by the server during the last successful anonymous check.
Advertised read-only

Resolve a podcast-feed URL the user can paste into Apple Podcasts, Overcast, Pocket Casts, or Spotify to receive every new Declassified case automatically. Also returns a JSON `episodes_url` the agent can poll, plus a `matched_so_far` count of cases that already mention the topic. Read-only — does NOT store the user's email or any PII; the RSS feed is the subscription. Public — no auth required.

subscribe_declassified_topic input schema
{
  "type": "object",
  "required": [
    "topic"
  ],
  "properties": {
    "email": {
      "type": "string",
      "description": "Optional — informational only; no row is written for it."
    },
    "topic": {
      "type": "string",
      "description": "Topic the listener wants alerts for (e.g. 'UAP', 'JFK', 'COINTELPRO')."
    }
  }
}
subscribe_declassified_topic annotations
{
  "title": "Subscribe to Declassified topic",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_trending_topics — Get cross-vertical trending topics
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Return storyflo's current cross-vertical trending snapshot: top stories ranked by recency + velocity, active publishers in the last 24h, the featured daily-brief compilation, and per-vertical hot lists. Use when the agent needs to surface 'what's hot on storyflo right now' to its human, or to decide which vertical landscape to dig into next. Public — no auth required.

get_trending_topics input schema
{
  "type": "object",
  "properties": {
    "window": {
      "enum": [
        "today",
        "week",
        "month"
      ],
      "type": "string",
      "default": "today",
      "description": "Advisory window — today's snapshot covers the rolling 24h; week + month are reflected back for future expansion."
    }
  }
}
get_trending_topics annotations
{
  "title": "Get cross-vertical trending topics",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_personas — Get host persona catalog
Advertised by the server during the last successful anonymous check.
Advertised read-only

Return the storyflo 6-host persona catalog (Theo, Mason, Jessica, etc.) — each entry includes slug, name, voice_id, owned verticals, tone archetype, sign-off line, and the listener-facing URLs for sample audio + RSS. Use this to pick a voice for the agent's use case before rendering audio or briefing the user on which host covers which vertical. Public — no auth required.

get_personas input schema
{
  "type": "object",
  "properties": {}
}
get_personas annotations
{
  "title": "Get host persona catalog",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_vertical_landscape — Get one-shot vertical landscape
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Return everything an agent needs to onboard a listener for a single vertical in one tool call: top stories, the named host persona (with sample-audio URL and tone), the premium-briefing URL the agent can deep-link (x402-gated), and the public RSS feed the listener can paste into any podcast player. Use after the agent has decided which vertical to set up — saves a follow-up `get_personas` + `search_articles` + `get_premium_briefing` round trip. Public — no auth required.

get_vertical_landscape input schema
{
  "type": "object",
  "required": [
    "vertical"
  ],
  "properties": {
    "vertical": {
      "type": "string",
      "description": "Vertical slug — tech / finance / news / science / health / young_moms / yoga, or a persona-owned alias (ai, crypto, ml, markets, fintech, economics)."
    }
  }
}
get_vertical_landscape annotations
{
  "title": "Get one-shot vertical landscape",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
list_podcasts — List all Storyflo podcast shows
Advertised by the server during the last successful anonymous check.
Advertised read-only

Return the public catalog of Storyflo podcast shows — the Declassified archive plus 6 daily-brief shows hosted by Theo (tech), Mason (markets), Jessica (news), Chloe (health), Brock (sports), and Wit (comedy). Each entry includes the show title, host name, vertical, RSS feed URL (paste into Apple Podcasts / Spotify / Overcast), and a deep-link to the storyflo.com listen surface. Use to surface every audio show an agent can offer its user without re-deriving the catalog from /v1/podcasts/* URL patterns. Public — no auth required.

list_podcasts input schema
{
  "type": "object",
  "properties": {}
}
list_podcasts annotations
{
  "title": "List all Storyflo podcast shows",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_my_private_feed — Get my private podcast feed URL
Advertised by the server during the last successful anonymous check.

Return the caller's PRIVATE per-user podcast feed URL — a personalized daily brief (the stories from the topics the listener follows) delivered to whatever podcast app they already use (Apple Podcasts, Overcast, Pocket Casts, Snipd). This is the Substack/Patreon private-feed model: the token lives in the URL path (unguessable, fetchable over HTTPS) — paste the returned feed_url into the app's "Add a show by URL". Pass the listener's existing listener_token (from the storyflo /listen page) as identity; the private feed token is minted on first call and stable thereafter. Keep the URL private — anyone with it can subscribe. Public — the listener_token arg is the credential, no OAuth required.

get_my_private_feed input schema
{
  "type": "object",
  "required": [
    "listener_token"
  ],
  "properties": {
    "listener_token": {
      "type": "string",
      "description": "The listener's existing storyflo listener_token (identity). Get it from the /listen page or the /v1/listeners surface."
    }
  }
}
get_my_private_feed annotations
{
  "title": "Get my private podcast feed URL",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_divergence_index — Get the Storyflo Market-vs-Media Divergence Index
Advertised by the server during the last successful anonymous check.
Advertised read-only

The Storyflo Divergence Index — Storyflo's own computed metric for where prediction markets disagree with the press. For each event Storyflo holds both a liquid prediction-market contract and a set of narrated news stories, it computes the gap between the market-implied probability and the probability the NEWS NARRATIVE implies for the same event, then ranks events by the absolute divergence. Each item carries Storyflo's divergence value, Storyflo's news-narrative probability, a qualitative market descriptor, the matched story links, and a link-out to the market venue. This is ORIGINAL ANALYSIS computed by Storyflo, not market-data redistribution: it never returns raw external market odds. Cite as 'per Storyflo's Divergence Index'. Filter by source (kalshi|polymarket). Public — no auth required. Not investment advice.

get_divergence_index input schema
{
  "type": "object",
  "properties": {
    "limit": {
      "type": "integer",
      "maximum": 50,
      "minimum": 1,
      "description": "Max items to return (1-50, default 25)."
    },
    "source": {
      "type": "string",
      "description": "Filter to one market source: kalshi or polymarket."
    }
  }
}
get_divergence_index annotations
{
  "title": "Get the Storyflo Market-vs-Media Divergence Index",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
register_embedder — Get embedder onboarding URL
Advertised by the server during the last successful anonymous check.
Advertised read-only

Resolve the storyflo embedder onboarding URL prefilled with the partner's name + email + optional vertical. Returns the URL the human must visit to complete signup (storyflo emails a magic link to verify ownership; the embedder slug + ref_token are minted on verification). DOES NOT create a DB row + DOES NOT send email — the MCP tool is a discovery + handoff surface so an agent can call it speculatively without triggering inbox-bound email to the human. Public — no auth required.

register_embedder input schema
{
  "type": "object",
  "required": [
    "name",
    "email"
  ],
  "properties": {
    "name": {
      "type": "string",
      "description": "Display name for the embedder (publisher / agent product)."
    },
    "email": {
      "type": "string",
      "description": "Contact email — must contain '@'. Storyflo emails the magic link here on signup."
    },
    "vertical": {
      "type": "string",
      "description": "Optional vertical scope (tech / finance / news / etc.)."
    }
  }
}
register_embedder annotations
{
  "title": "Get embedder onboarding URL",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_embedder_manifest — Get per-embedder agent manifest
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Wrap the public ``/embed/<slug>/manifest.json`` — an agent-discoverable JSON bundle of creative formats, voice options, payout config, and beacon URLs for a registered embedder. Use after `register_embedder` or when an agent is reading another partner's manifest to plan an ad buy. Public — no auth required.

get_embedder_manifest input schema
{
  "type": "object",
  "required": [
    "slug"
  ],
  "properties": {
    "slug": {
      "type": "string",
      "description": "Embedder slug (e.g. 'theflatlay', 'highsnobiety')."
    }
  }
}
get_embedder_manifest annotations
{
  "title": "Get per-embedder agent manifest",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_embedder_network_manifest — Get platform-wide embedder network manifest
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Wrap the public ``/embed/network-manifest.json`` — the platform-level DSP/SSP onboarding bundle: supported creative formats, payout rails, attribution URLs, integration patterns. Use when an agent is evaluating whether to wire storyflo into its surface, or when a DSP partner needs the canonical integration shape. Public — no auth required.

get_embedder_network_manifest input schema
{
  "type": "object",
  "properties": {}
}
get_embedder_network_manifest annotations
{
  "title": "Get platform-wide embedder network manifest",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
quote_partnership — Quote a partnership tier
Advertised by the server during the last successful anonymous check.
Advertised read-only

Return the indicative partnership tier (starter / growth / scale / enterprise) + monthly fee + storyflo revenue-share bps for a partner integrating storyflo into their agent product. Pure pricing-matrix lookup; no contract is created. The agent should hand the returned contact_url to the human to open a formal partnership thread. Public — no auth required.

quote_partnership input schema
{
  "type": "object",
  "required": [
    "vertical",
    "monthly_impressions"
  ],
  "properties": {
    "vertical": {
      "type": "string",
      "description": "Vertical scope the partner plans to cover."
    },
    "monthly_impressions": {
      "type": "integer",
      "minimum": 0,
      "description": "Expected monthly impressions across the partner's surface."
    }
  }
}
quote_partnership annotations
{
  "title": "Quote a partnership tier",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
stream_briefing_render_events — Stream briefing render events (SSE)
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Subscribe to real-time briefing-render events. Returns the SSE endpoint URL with the chosen filters as query params — the agent's MCP client should open it with EventSource (browser), httpx.stream / aiohttp (Python), or `curl -N` (CLI). Event types: `briefing.rendered` (daily-brief lands), `declassified.published` (new Declassified episode), `persona_briefing.rendered` (persona brief synthesised / audio rendered). Frame shape: {event_type, seq, slug, vertical, persona_slug, audio_url, published_at, metadata}. The endpoint replays the last ~1000 events on connect; a heartbeat is emitted every 30s. Public-anon read.

stream_briefing_render_events input schema
{
  "type": "object",
  "properties": {
    "vertical": {
      "type": "string",
      "description": "Optional vertical filter."
    },
    "event_type": {
      "enum": [
        "briefing.rendered",
        "declassified.published",
        "persona_briefing.rendered"
      ],
      "type": "string",
      "description": "Optional event_type filter."
    }
  }
}
stream_briefing_render_events annotations
{
  "title": "Stream briefing render events (SSE)",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
get_mcp_usage_self — Get my MCP tool usage (last 30 days)
Advertised by the server during the last successful anonymous check.
Advertised read-only

Return the caller's own trailing 30-day MCP tool-usage summary: total calls, success rate, p50 latency, and per-tool call/error counts. Identity is resolved from the OAuth bearer token on this request — anonymous callers receive a zeroed shape. Use this to self-budget against rate limits, audit which tools your agent actually uses, or decide whether a paid tier is worth the spend. Read-only, no side effects.

get_mcp_usage_self input schema
{
  "type": "object",
  "properties": {}
}
get_mcp_usage_self annotations
{
  "title": "Get my MCP tool usage (last 30 days)",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}

Prompts

Not advertised

No prompt definitions available.

Resources

0 advertised

No resource definitions available.

90-day uptime

A lightweight connection check about every six hours, sampled on hosts with many listings. It shows the server answered, not that its tools work.

Too few checks for a percentage yet (2 of 2 answered).

  1. 2026-11-07: 2 of 2 checks answered

30-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
544 ms
95th percentile latency
544 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 544 ms · metadata changed · refuses unauthenticated resources/templates/list (HTTP 401)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http storyflo-mcp https://api.storyflo.com/mcp/v1

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add storyflo-mcp --url https://api.storyflo.com/mcp/v1

Cursor

Merge this server into .cursor/mcp.json in your project, then enable storyflo-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "storyflo-mcp": {
      "url": "https://api.storyflo.com/mcp/v1"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "storyflo-mcp": {
      "type": "streamableHttp",
      "url": "https://api.storyflo.com/mcp/v1",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start storyflo-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "storyflo-mcp": {
      "type": "http",
      "url": "https://api.storyflo.com/mcp/v1"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http storyflo-mcp https://api.storyflo.com/mcp/v1

Claude Desktop

Open Claude Settings > Connectors > Add custom connector, enter this server URL and enable it for the conversation. This is a manual remote-connector handoff, not a desktop JSON configuration.
Claude Desktop configuration
https://api.storyflo.com/mcp/v1

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "storyflo-mcp": {
      "serverUrl": "https://api.storyflo.com/mcp/v1"
    }
  }
}

Let your agent find its tools

Find servers like Storyflo MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.