Skip to main content
Glama
substack-saved-mcp

substack-saved-mcp

by toniher

search_saved_posts

Search cached saved Substack posts by full-text query and filter by publication, audience, date, or read state; optionally search reading history to find viewed posts.

Instructions

Perform full-text FTS5 search across cached saved posts.

history=True searches the reading history instead: posts viewed on Substack (seen_at set), saved or not (is_saved tells which).

Searches title, excerpt, publication name, author, and content text (content is only present for posts fetched via get_post_content). query uses SQLite FTS5 syntax; a malformed query falls back to a substring match. Date filters take ISO 8601 strings (e.g. "2026-01-31"). Allows filtering by publication name, audience tier (see list_audiences for cached values, e.g. "everyone", "only_paid"), original post date (published_at), saved date (saved_at), and read_state ('unread', 'in_progress', 'finished', 'unfinished' (unread + in_progress), or 'started' — a post is 'finished' once its high-water reading progress crosses a threshold, default 0.95).

Input Schema

NameRequiredDescriptionDefault
limitNo
queryYes
historyNo
audienceNo
read_stateNo
publicationNo
saved_afterNo
saved_beforeNo
published_afterNo
published_beforeNo

Output Schema

NameRequiredDescriptionDefault
resultYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changedv0.4.0
    • addedInput schema / properties / history
      Added value: +{
      +  "default": false,
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / result / items / properties / seen_at
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null
      +}
  2. Changed7 schema fields changedv0.3.1
    • addedInput schema / properties / read_state
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null
      +}
    • addedOutput schema / properties / result / items / properties / is_fully_read
      Added value: +{
      +  "readOnly": true,
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / result / items / properties / is_viewed
      Added value: +{
      +  "default": 0,
      +  "type": "integer"
      +}
    • addedOutput schema / properties / result / items / properties / max_read_progress
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "number"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null
      +}
    • addedOutput schema / properties / result / items / properties / minutes_remaining
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "integer"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "readOnly": true
      +}
    • addedOutput schema / properties / result / items / properties / read_progress
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "number"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null
      +}
    • changedOutput schema / properties / result / items / required
      Previous value: -[
      -  "url",
      -  "title",
      -  "publication_name"
      -]New value: +[
      +  "url",
      +  "title",
      +  "publication_name",
      +  "is_fully_read",
      +  "minutes_remaining"
      +]
  3. First observedv0.1.0

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations, the description carries the burden and does well: it discloses that content text is only searchable for posts fetched via get_post_content, that malformed queries fall back to substring matching, and the threshold semantics behind 'finished'. Gaps remain on pagination/limit behavior and result ordering, but the important behavioral caveats are surfaced.

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

Conciseness4/5

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

Front-loads the core purpose and the history mode before the filter details, and every clause is substantive. The long parenthetical defining read_state is dense but earns its space by enumerating non-obvious enum values.

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 10-parameter search tool with an output schema (so return values need no explanation), the description covers mode selection, query syntax, and nearly all filter semantics. The one substantive omission is limit/pagination behavior, which the schema only implies via a default.

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

Parameters4/5

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

Schema coverage is 0% for 10 parameters, so the description must compensate and largely does: it defines FTS5 query syntax and its fallback, ISO 8601 date format, history semantics, audience, publication, published_at vs saved_at date filters, and the full read_state vocabulary including compound values. Only 'limit' is left unaddressed, so it falls short of a 5.

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?

States a specific verb and mechanism (full-text FTS5 search) over a specific resource (cached saved posts), and immediately names the alternate mode (history=True searches reading history instead). An agent can distinguish it from list_saved_posts / get_saved_post / search_saved_notes without opening any schema.

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?

Clearly explains when to use the default mode versus history=True, and points to list_audiences for valid audience values. It does not explicitly say when to prefer list_saved_posts over searching, but the search-vs-list distinction is strongly implied by 'full-text FTS5 search'.

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