Skip to main content
Glama

Substack Read

substack_read
Read-only

Read other people's Substack content and research the market. Read only. Actions: list_articles, get_article, search_articles, get_comments (a publication's posts); list_subscriptions (who you follow), get_inbox (new posts from them), get_feed (For You); fetch_notes, get_profile_feed (any author's Notes); catalog (a creator's full archive with SEO fields); search_topic (posts and Notes across all of Substack, by topic); get_publication (a publication's public profile); get_engagement (who engaged with YOUR publication); newsletters_search, newsletters_intersection, newsletters_analytics, newsletters_suggest_queries (130,000+ newsletter corpus); workflows_search, workflows_run (guided growth workflows: run the loaded workflow, do not print it). get_inbox, get_feed, list_subscriptions and get_engagement need the QVN Chrome extension signed in on substack.com. Keep limit at 20 or less per call to avoid Substack 429s. Call action help for parameters.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "action": "<action>"
    },
    "name": "substack_read"
  }
}

Input Schema

NameRequiredDescriptionDefault
maxNocatalog only: cap the number of posts returned (newest first). Omit for the full catalog.
daysNoget_engagement only: window in days (1-30, default 7). Always sent, so the MCP window does not inherit the HTTP route's narrower 2-day default — "who engaged with me" over 2 days is a near-empty answer.
kindNosearch_topic only: "all" (default), "posts" or "notes".
slugNoget_article, get_comments: article slug (e.g. 'my-article-title') or numeric post ID (e.g. '184929446'). workflows_run: the workflow slug, e.g. "niche-sizer" (from workflows_search).
sortNolist_articles: 'new' (default), or 'top' — Substack's own composite ranking, NOT the same as sorting by the returned likes+comments+restacks.
syncNoget_engagement only: spawn a background refresh first. The response still returns the CURRENT cache — call again after ~2 min for the refreshed set and compare stale_hours. Nothing refreshes this cache on a schedule, so this is the only way to make it current.
tierNonewsletters_search: filter by tier (0=free, higher numbers=premium tiers).
exactNonewsletters_search: true = strict keyword matching only; false (default) = synonym-expanded semantic matching.
fuzzyNonewsletters_analytics / newsletters_intersection: DEFAULT true = match as free text over newsletter name/description/author (works for non-tag terms like "vibe coding"). Pass false for a strict curated-tag match.
limitNoResults per call. Max 50 for list_articles, search_articles, get_feed, fetch_notes, get_profile_feed; max 100 for newsletters_search and newsletters_intersection (checked per action, server side). get_feed is capped to 20 by the backend. Defaults: 12 (list_articles, search_articles), 20 (get_feed, fetch_notes, newsletters_*). Keep batches small: large loops can trigger Substack 429s.
pagesNoget_inbox, get_feed, get_profile_feed: pages to fetch (~20 items per page). Default 1; use 3–5 for 48h coverage. Ignored by get_feed when min_date is set.
queryNoSearch keyword. Required for search_topic, search_articles and newsletters_search (e.g. "AI newsletters for founders"). Optional keyword filter for list_articles and workflows_search.
actionYesThe operation to perform. Current actions: list_articles, get_article, search_articles, get_comments, list_subscriptions, get_inbox, get_feed, fetch_notes, get_profile_feed, catalog, get_publication, search_topic, get_engagement, newsletters_search, newsletters_intersection, newsletters_analytics, newsletters_suggest_queries, workflows_search, workflows_run. Pass "help" for the live list with parameters; actions added after you connected appear there and work without reconnecting.
cursorNosearch_topic only: next_cursor from the call before, for the next page.
offsetNolist_articles: pagination offset. Default 0.
keywordNonewsletters_analytics: the single keyword to analyze (e.g. "productivity").
optionsNoExtra parameters for an action whose params are not listed in this schema (see action "help"). Parameters that ARE listed in this schema must be passed at top level; here they are ignored.
sort_byNonewsletters_search: sort order. "relevance" (default), "subscribers", or "recent".
categoryNoworkflows_search: optional category filter. All workflows are category "workflow"; unknown values are ignored.
keywordsNonewsletters_intersection: 2–5 keywords. Returns newsletters matching ALL of them.
min_dateNoget_feed only: ISO date (e.g. "2026-06-07"). Fetches pages until all items are older than this date; use instead of pages for time-window queries.
subdomainNoSubstack subdomain (e.g. 'platformer', 'stratechery'). Required for list_articles, search_articles, catalog, get_publication. Optional for get_article and get_comments — auto-detected when passing a numeric post ID.
since_dateNocatalog only: ISO date (e.g. "2026-01-01"). Returns only posts on/after this date.
descriptionNonewsletters_suggest_queries: natural-language description of what you want to analyze.
check_answeredNoget_engagement only: drop items already answered on Substack.
substack_inputNofetch_notes and get_profile_feed: Substack URL, @handle, or subdomain. Examples: 'jennyouyang', '@jennyouyang', 'https://jennyouyang.substack.com'.
min_subscriber_countNonewsletters_search: only newsletters with at least this many subscribers.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed5 schema fields changed
    • changedInput schema / properties / action / description
      Previous value: -"The operation to perform. Current actions: list_articles, get_article, search_articles, get_comments, list_subscriptions, get_inbox, get_feed, fetch_notes, get_profile_feed, catalog, get_engagement, newsletters_search, newsletters_intersection, newsletters_analytics, newsletters_suggest_queries, workflows_search, workflows_run. Pass \"help\" for the live list with parameters; actions added after you connected appear there and work without reconnecting."New value: +"The operation to perform. Current actions: list_articles, get_article, search_articles, get_comments, list_subscriptions, get_inbox, get_feed, fetch_notes, get_profile_feed, catalog, get_publication, search_topic, get_engagement, newsletters_search, newsletters_intersection, newsletters_analytics, newsletters_suggest_queries, workflows_search, workflows_run. Pass \"help\" for the live list with parameters; actions added after you connected appear there and work without reconnecting."
    • addedInput schema / properties / cursor
      Added value: +{
      +  "description": "search_topic only: next_cursor from the call before, for the next page.",
      +  "maxLength": 1000,
      +  "type": "string"
      +}
    • addedInput schema / properties / kind
      Added value: +{
      +  "description": "search_topic only: \"all\" (default), \"posts\" or \"notes\".",
      +  "enum": [
      +    "all",
      +    "posts",
      +    "notes"
      +  ],
      +  "type": "string"
      +}
    • changedInput schema / properties / query / description
      Previous value: -"Search keyword. Required for search_articles and newsletters_search (e.g. \"AI newsletters for founders\"). Optional keyword filter for list_articles and workflows_search."New value: +"Search keyword. Required for search_topic, search_articles and newsletters_search (e.g. \"AI newsletters for founders\"). Optional keyword filter for list_articles and workflows_search."
    • changedInput schema / properties / subdomain / description
      Previous value: -"Substack subdomain (e.g. 'platformer', 'stratechery'). Required for list_articles, search_articles, catalog. Optional for get_article and get_comments — auto-detected when passing a numeric post ID."New value: +"Substack subdomain (e.g. 'platformer', 'stratechery'). Required for list_articles, search_articles, catalog, get_publication. Optional for get_article and get_comments — auto-detected when passing a numeric post ID."
  2. First observed

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond readOnlyHint/openWorldHint, it discloses that get_inbox, get_feed, list_subscriptions and get_engagement require the QVN Chrome extension signed in on substack.com, and it warns that batches above 20 risk Substack 429s. Those are exactly the failure modes an agent cannot infer from annotations or schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and the read-only constraint are correctly front-loaded, and little is pure filler. However, the 19-action catalog is delivered as one dense semicolon-chained paragraph that is hard to scan, and a reader must parse the whole block to locate a single action's routing hint.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 19-action, 27-parameter mega-tool with no output schema, the definition covers routing, auth prerequisites, rate-limit hygiene and the live-help escape hatch. What is missing is any sense of what results look like per action and how pagination composes across the cursor/offset/pages/min_date options.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema itself explains each parameter in detail, including per-action limits and defaults, so the description only needs to not interfere. Its contribution is the pointer 'Call action `help` for parameters', which is redundant with (and slightly weaker than) the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening states a specific verb and resource — 'Read other people's Substack content and research the market. Read only.' — and the explicit 'other people's' plus 'Read only' distinguishes it from the write sibling and the own-publication sibling. The action enumeration then makes concrete exactly what surfaces are reachable (articles, comments, Notes, newsletters, workflows).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Each action is annotated with its scope in parentheses (e.g. 'get_comments (a publication's posts)', 'catalog (a creator's full archive with SEO fields)', 'get_engagement (who engaged with YOUR publication)'), which effectively routes an agent to the right action. It also names prerequisites per action. It stops short of explicit when-not-to-use or cross-sibling steering.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources