Tools
The eight MCP tools, what each one answers, and the response contract they all share.
The server registers eight tools and nothing else. Ask it for the list and you get exactly these:
| Tool | Answers | Required arguments |
|---|---|---|
recommend | Which library or service to use for a task | task |
compare | Which of 2 to 4 named candidates wins, and when the others do | options |
alternatives | Open-source or self-hosted replacements for a product | to |
traps | Known breakages for a library, narrowed to a version | library or id |
skill | The SKILL.md procedure attached to a verdict | slug |
design | Design system, tokens, and anti-patterns for a screen | screen |
docs | Official docs URL, llms.txt, and latest version | library |
submit_trap | Records a breakage you hit, for review | library, version, symptom, fix |
Calling one
The endpoint is https://mcp.wellworn.dev/mcp, Streamable HTTP, stateless. Every POST builds a fresh server, so there is no session to open and no session id to carry. Both header values below are required; without them the transport answers 406.
curl -sX POST https://mcp.wellworn.dev/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"docs","arguments":{"library":"better-auth"}}}'The reply comes back as one Server-Sent Event, so the body starts with event: message and the JSON sits on the data: line. MCP clients unwrap that for you.
The response contract
Every tool returns one text block. The result carries a content array with exactly one entry of type text, no output schema, and no structuredContent field, so an agent reads the answer instead of parsing an envelope. Nothing is paginated.
A served answer ends with a remaining: line, appended after the tool text:
DOCS Better Auth (latest 1.7.3)
docs https://www.better-auth.com/docs
llms.txt https://www.better-auth.com/llms.txt
remaining: 49The number is how many calls are left in the current window: the day for an anonymous caller, the month for a key. Details are on limits.
When the window is spent, the limit line replaces the answer and the remaining: line is gone:
limit reached: no-key 60/60 today (resets 2026-09-09T00:00:00.000Z). Free key or plans: https://wellworn.dev/pricingThat block is a normal result, not a JSON-RPC error, and isError is not set on it. The same is true of every "no verified verdict yet" answer. isError: true appears in two places only: arguments that fail the input schema, and the internal error (ref …) line. Errors lists both with their causes.
The RECHECK flag
A verdict whose pick has moved a major version since it was verified, or whose expiry date has passed, is served with [RECHECK] in the first line:
VERDICT [RECHECK] auth for a Next.js app, solo dev, free tier, email + Google loginThe answer keeps being served, because a checked but stale answer beats a fresh guess, but the version numbers in it are the part to distrust. How verdicts are made covers the nightly pass that sets the flag and what clears it.
Size
recommend, compare and design render through the same function, which caps its block at 3,200 characters, roughly 800 tokens. When a verdict does not fit, lines are dropped in this order: traps from the least severe up, then AVOID, then ALT. PICK and VERIFIED are never dropped, and the trap header changes to TRAPS (2 of 5) so the block admits what it left out.
The other tools are naturally short. traps lists at most eight rows; a single trap's FIX line is cut at 2,400 characters; docs is at most four lines and skill is two. The remaining: line is added after the cap, so the largest block the server can return is about 3,215 characters.