Skip to main content
Glama
io.github.lsmman/fetchive

io.github.lsmman/fetchive

Official
by lsmman

Fetchive

Throw links at it. Get workspace-ready pages back.

An MCP server for people who collect more links than they can process. Paste a KakaoTalk export, a Slack dump, or a bare list of URLs, and Fetchive pulls out every link, skips what you already saved, reads what is behind each one — YouTube transcripts, article text — and hands your assistant a ready-to-save payload for each.

Everything it reads stays searchable, so last month's links can answer this month's question.

It does not write to your workspace. It prepares the page and lets whatever you already have connected — Notion, Obsidian, anything — do the saving. No second login, no second place for your data to sit.


Install

uvx fetchive

Or add it to your MCP client:

{
  "mcpServers": {
    "fetchive": {
      "command": "uvx",
      "args": ["fetchive"]
    }
  }
}

For local speech-to-text on videos with no captions:

uvx --with 'fetchive[stt]' fetchive

That extra needs ffmpeg on your PATH (brew install ffmpeg) and downloads a Whisper model on first use.


Related MCP server: tldw-mcp

Using it

Say this to your assistant:

Here's my link dump from this week, archive it → (paste)

Behind that, one tool call does the work:

  1. archive_batch parses the links, skips what is already saved, extracts transcripts, and starts working in the background

  2. get_batch_status reports progress and returns the finished payloads

  3. Your assistant saves each one with your workspace tool

  4. record_archived tells Fetchive it landed, so next week's dump skips it

Later, ask it what you saved:

지난달에 RAG 청킹 얘기 어디서 봤더라?

search_archive runs full-text search over every transcript and article body it has read — not just titles — and Korean works, which the usual word tokenizer does not manage.

The other tools — ingest_links, extract_youtube_script, check_duplicate, format_for_notion, forget_archived — are the individual steps, there for when you want to inspect or repair something rather than run the whole flow.

A link it cannot read fails rather than becoming an empty page. A row that says only "here is a URL I could not open" looks like the work was done.


How transcripts actually get extracted

This is the hard part of the problem, and no single method survives YouTube for long. Fetchive tries four, in order, and stops at the first that returns words:

Order

Method

Cost

Why it is in the chain

1

youtube-transcript-api, direct

free

Fastest when it works

2

yt-dlp captions

free

Different endpoints, so it survives blocks that stop #1

3

youtube-transcript-api via proxy

cheap

For when your IP itself is the problem

4

yt-dlp audio → local Whisper

slow

Works on videos with no captions at all

Every attempt is recorded with a reason it failed — blocked, no_captions, unavailable, too_long, and so on — so a run tells you not only what came out but which parts of the pipeline still work. Successful transcripts are cached, so asking twice is free.

Captions are chosen by what exists, not by what you hoped for: a Korean video with only Korean captions gets its Korean transcript rather than being reported as having none.


Configuration

Everything is optional.

Variable

Default

What it does

FETCHIVE_DB_PATH

~/.fetchive/fetchive.db

Where your archive index and transcript cache live

FETCHIVE_LANGUAGES

ko,en

Preferred caption languages, best first

WEBSHARE_PROXY_USERNAME / _PASSWORD

—

Enables the proxy step. Without these it is skipped

FETCHIVE_ENABLE_STT

true

Set to false to never fall back to speech-to-text

FETCHIVE_WHISPER_MODEL

base

Larger is slower and more accurate

FETCHIVE_MAX_STT_DURATION

3600

Refuse to transcribe anything longer, in seconds

FETCHIVE_BATCH_WORKERS

3

Concurrent extractions. YouTube dislikes more

FETCHIVE_QUOTE_WORD_LIMIT

15

Longest verbatim quote allowed out of the server

FETCHIVE_TRANSPORT

stdio

http for a hosted deployment


Transcripts are extracted for your own reading and cached locally. Putting that text into a stored page is a different act, so what Fetchive prepares for your workspace is a summary, a word count, and at most one quote of fifteen words per source — enforced in the payload builder rather than left to whoever is calling. The link to the original always travels with it.

Fetchive is a tool for organising material you have chosen to keep. It is not for republishing anyone's work, and you remain responsible for what you do with what it extracts. If a source's terms do not permit you to store its content, do not archive it.


Your data

Everything stays on your machine, in one SQLite file. Fetchive has no server, no account, and no telemetry. It talks to YouTube to fetch transcripts, and to a proxy only if you configure one. Nothing is ever sent to Fetchive's authors.

To delete everything: rm -rf ~/.fetchive. To remove one item, call forget_archived with its URL.

Full policy: https://github.com/lsmman/fetchive/blob/main/PRIVACY.md


Development

uv sync
uv run pytest
uv run ruff check src tests

Network tests are deselected by default. To run them against real YouTube:

uv run pytest -m network

MIT licensed.

Available Tools

11 tools
add_summarySubmit a summary you wroteA

Record a summary and tags for one extracted item. Use this after summarise_pending hands you a prompt to write yourself. The summary is checked for copying the source before it is kept, and the item then appears in ready_to_save.

Inputs: url (required), summary (required), batch_id (required), tags, +1 more. Returns: object

archive_batchArchive a pile of linksA

Parse every link out of pasted text (a KakaoTalk or Slack export, a bare list, anything), skip what is already archived, extract YouTube transcripts, and prepare a page payload for each one. Returns a batch ID immediately; extraction runs in the background. Poll get_batch_status.

Inputs: text (required). Returns: object

check_duplicateCheck for a duplicateA
Read-onlyIdempotent

Has this URL already been archived? Matches the canonical form of the URL, and if a title is supplied also compares it against archived titles to catch re-uploads and mirrors.

Inputs: url (required), title. Returns: object

extract_youtube_scriptExtract a YouTube transcriptA

Get the transcript for one YouTube video, trying caption APIs, yt-dlp, and local speech-to-text in turn. Reports which method worked and why the others did not. Cached, so asking twice is free.

Inputs: url (required), use_cache. Returns: object

forget_archivedForget an archived pageA
DestructiveIdempotent

Remove a URL from the archive index, so it counts as new again. Use when the page it points to was deleted from the workspace. Does not touch the workspace itself.

Inputs: url (required). Returns: object

format_for_notionPrepare a page payloadA
Read-onlyIdempotent

Shape one link into a page payload: properties, the workspace's existing tag vocabulary, and instructions for classifying against it. Quotes are capped and transcripts are never included verbatim.

Inputs: url (required), tags, title, quotes, +1 more. Returns: object

get_batch_statusCheck batch progressA
Read-onlyIdempotent

Progress for a running or finished batch. When state is 'completed', ready_to_save holds one payload per item that is ready to write to the workspace, and items explains anything that failed or was skipped.

Inputs: batch_id (required). Returns: object

record_archivedRecord an archived pageA

Tell Fetchive that a URL has been saved to the workspace, and where. Call this after every successful save — it is the only way duplicate detection learns what exists.

Inputs: url (required), tags, title, page_url. Returns: object

search_archiveSearch the archiveA
Read-onlyIdempotent

Full-text search across everything archived — transcripts and article bodies, not just titles. Use this to answer questions about what the user has already saved, or to find the source of a half-remembered idea. Returns matching excerpts with the workspace page link where one was recorded.

Inputs: query (required), limit. Returns: object

summarise_pendingSummarise what was extractedA

Write summaries and tags for items a batch has extracted but not yet summarised, using your own model. Call this after archive_batch reports items in needs_summary, and call it repeatedly until remaining reaches zero. Works a few items at a time on purpose: a thousand transcripts cannot go through one request.

Inputs: batch_id (required), limit. Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.1/5.0

    Scored across 11 tools

    Disambiguation4/5

    Most tools have clearly distinct purposes, but archive_batch and ingest_links both parse links from text, which could cause misselection. summarise_pending and add_summary are also related, though descriptions clarify their different roles.

    Naming Consistency5/5

    All tool names follow a consistent verb_noun pattern in snake_case (archive_batch, get_batch_status, ingest_links, etc.). The naming is predictable and easy to reason about.

    Tool Count5/5

    11 tools is well within the ideal range for a focused archiving workflow. Each tool supports a distinct step in the pipeline: extraction, transcription, summarization, search, and duplicate management.

    Completeness4/5

    The core workflow is well-covered: link extraction, YouTube transcript retrieval, summary generation, archiving, search, and duplicate detection. Minor gaps exist, such as no direct update or fetch-by-ID for individual archived items, but the server's purpose is well-served.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      MCP server that extracts YouTube video transcripts (including metadata) as Markdown, enabling AI to summarize and discuss video content without watching it.
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Persistent knowledge-base MCP server. Semantic search with source citations over saved YouTube videos, podcasts, articles and PDFs — one endpoint for every MCP-capable AI client.
      28
      Elastic 2.0
    • A
      license
      A
      quality
      C
      maintenance
      An MCP server that extracts rich metadata (title, description, duration, chapters, subtitles, statistics, etc.) from media URLs across thousands of sites using yt-dlp, and also provides transcript fetching and search capabilities.
      3
      1
      MIT