Reading links your agent can't open

Your agent is good at reading. It just can't open half the internet.

Hand Claude Code a Xiaohongshu link from a design review, a Douyin video a colleague sent, a TikTok your competitor posted — and it fetches the URL, gets an app-download shell, and tells you it couldn't find anything useful. It isn't wrong. There genuinely is nothing there.

curl the link HTTP 200 202 KB <title>小红书</title> no caption · no text · no images digest_url transcript ocr_text images[] key_points the post, as text
Same URL, same 200 status. The difference is who asks and what they do with what comes back.

This is a post about the second box: how to call it, and three things people actually do with it.

The agent calls it, not you

One command:

claude mcp add --transport http linkdigest \
  https://linkdigest.dev/mcp \
  --header "Authorization: Bearer ld_live_..."

That registers one tool, digest_url(url, format, job_id). Only url is required.

The part that matters is what happens next: you never mention it again. The tool description tells the agent to call it whenever it meets a social link it cannot read, so the agent reaches for it on its own, mid-task, the way it reaches for grep.

your agent Claude Code MCP server digest_url the post video · images url fetch transcript · on-screen text · image descriptions

your key never leaves the header; the media never lands on your machine

Cursor takes the same server in ~/.cursor/mcp.json:

{
  "mcpServers": {
    "linkdigest": {
      "url": "https://linkdigest.dev/mcp",
      "headers": { "Authorization": "Bearer ld_live_..." }
    }
  }
}

What actually comes back

Not a summary. The parts:

curl -X POST https://linkdigest.dev/api/v1/digest \
  -H "Authorization: Bearer ld_live_..." \
  -H "Content-Type: application/json" \
  -d '{"url": "https://v.douyin.com/..."}'

A real response, trimmed — this is a Douyin video, run against production while writing this paragraph:

platform           'douyin'
author             '逸蒙的赛博空间'
posted_at          '2026-08-27'
transcript_source  'asr'
cached             True   credits 0
degraded           []
transcript[0]      {"t": 0, "text": "谁能想到,就这么一个丑萌小玩意儿…"}
key_points[0]      "该AI产品名为Tolen,主打「记住你」的核心功能…"

Fifteen fields in total: platform, author, title, posted_at, caption, transcript, ocr_text, images, key_points, raw_markdown, source_url, transcript_source, degraded, plus cached and credits.

Two of those are worth pointing at.

transcript_source says how you got the words — native_captions, asr, or none. Captions the platform already had are exact; speech recognition is not. A pipeline that treats those identically will eventually quote a mis-heard number back at someone as fact.

degraded is a list of what didn't fully work, in plain words. Empty on a clean run. It exists because of a specific bug: a note was digested during a provider rate-limit storm, every vision batch failed, the per-batch handler swallowed each one, and the job returned images: 0, ocr: 0 — a well-formed, completely empty result, which was then cached for thirty days. Nothing downstream could tell an empty answer from an easy one. Now it can.

The pipeline, and why some links take two calls

resolve share link fetch cookies, media read ASR, vision, OCR structure fields, key points
A cached link skips all four and returns in about a second. A fresh video does not.

read is where the time goes, because it is the only stage that has to watch or listen to anything. Measured: a Xiaohongshu note with images takes one to two minutes; a YouTube video with captions about two and a half.

That is longer than one HTTP request should wait, so the API hands the work back:

POST /api/v1/digest
→ 202 {"pending":true,"jobId":"abc…","poll":"/api/v1/digest/abc…","retryAfter":15}

Collect it with the same key at that poll path — 202 while it runs, 200 with the digest when it's done. Over MCP you don't do any of this by hand: the tool tells the agent to call digest_url again with the job_id and no url, and the agent does.

Three things people build with it

1. The agent that reads the link itself

The one that needs no code. A teammate drops a Douyin link in an issue; the agent working that issue reads it without anyone transcribing anything. This is the whole reason the tool description is written the way it is — it is instructions for a machine deciding whether to reach for a tool, not marketing copy.

2. A list of links becomes a table

Fifty URLs in, fifty rows out — one POST each, or the Apify Actor if you'd rather not write the loop. The dataset has a row per link with the transcript, the on-screen text and the key points already separated.

Worth knowing what you're joining: there is real demand for exactly this shape of work. A single competing Douyin scraper on the Apify Store has over 1.5 million runs. Almost all of them return metadata — view counts, captions, author handles. Very few return what was actually said.

3. Watching what a competitor publishes

The same loop on a schedule. A creator's video output becomes searchable text over time, so "when did they first mention pricing" is a grep instead of an afternoon of watching.

This is the use case where transcript_source earns its place again. If you're going to quote a competitor's claim back to your own team, it matters whether a human captioned it or a model guessed at it.

What it costs, and why it isn't flat

A digest is not a unit of cost. Measured against real runs:

measured cost to serve one digest

web article $0.000163

note, 17 images $0.002654

video, 2.4 min $0.006279

video, 19 min $0.089900 — 550× the web article

Which is why pricing counts the two things that drive that spread — images to describe, minutes to transcribe — rather than counting requests. One credit covers a typical post and its first six images; each further six images adds one, and each minute of media adds two.

Cached links are free and never counted. Anything anyone has ever digested comes back in about a second, for nobody's credits.

Where it stops

The honest table, because finding out after you've wired something in is worse than knowing now:

  • Works: Xiaohongshu, Douyin, TikTok, YouTube, X, ordinary web pages.
  • Bilibili returns HTTP 412 to a datacenter address. Needs a residential proxy.
  • Instagram and Facebook need a logged-in session for most posts.

Three free digests, no card, if you want to check any of that yourself.


This is the write-up behind LinkDigest, which does the above as a hosted service — with an MCP server for Claude Code and Cursor, a REST API, and three free digests to try it.