Medium Reader MCP
This MCP server gives Claude and other MCP clients read/write access to your Medium account through 17 tools. Here's what you can do:
Read your feeds: Get your Following and For you feeds (get_feed), page through them, filter by recency.
Read full posts: Fetch any Medium post (including member-only and custom-domain posts) as markdown or text, with paging for long posts (read_post).
Get recent posts from a specific author or publication (get_recent_posts).
Search Medium for posts by keyword (search_posts).
List who you follow (authors or publications) (list_following).
View your reading lists: list them, get posts in a list (list_reading_lists, get_list).
View reading history (get_reading_history).
Manage follows: follow/unfollow authors or publications (follow, unfollow).
Mute/unmute authors or publications to hide their posts (mute, unmute).
Manage saved posts: save to or remove from your reading list or named lists (save_to_list, remove_from_list).
Clap for posts (up to 50 per post) and undo claps (clap, undo_clap).
Check auth status: verify login, membership, and session validity (auth_status).
Provides access to a Medium account for reading Following and For you feeds, full member-only stories, searching posts, managing follows, reading lists, and clapping.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Medium Reader MCPWhat's new in my Medium feed today?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Medium Reader MCP
Ask Claude what's new in your Medium feed, and have it read member-only stories for you.
An MCP server that gives Claude (and any other MCP client) access to your Medium account: your Following and For you feeds, full member-only posts, the authors and publications you follow, search, and your reading lists. It can also follow and unfollow, save posts to lists, and clap. You log in once in a browser window; no API keys or cookie exporting.
Quick start · Other clients · Hermes digest · Tools · Logging in · Privacy and security · How Medium's feeds behave · Troubleshooting
What it uses
What | Where | Needed? |
Your Medium account | Yes. A membership is needed to read member-only stories in full | |
Node.js 20+ | Yes | |
MCP SDK, Zod, undici | npm ( | Yes, installed by |
Chrome or Edge | Your existing install, driven by | Optional. Only for the browser login; you can paste cookies instead |
Medium no longer issues API tokens, and its old API never covered reading. This server calls the same GraphQL endpoint Medium's website uses, with your own session, so it can only see what you can see when logged in. No browser runs while you use it; the browser is only for logging in.
Requests to Medium go over HTTP/1.1 through the undici package, not Node's built-in fetch. Medium's Cloudflare protection returns 403 to Node's HTTP/2 client. Node 26's built-in fetch (undici 8) uses HTTP/2 whenever the server offers it, so it would be blocked on every request.
Related MCP server: Personal Cronometer MCP
Quick start
git clone https://github.com/wkbaran/medium-reader-mcp.git
cd medium-reader-mcp
npm install && npm run build
node dist/cli.js login # a browser window opens; sign in to Medium as usual
node dist/cli.js install # registers the server with Claude CodeRestart Claude Code (a session that's already running won't pick up new servers), then try:
"What's new in my Medium feed today?"
"Summarize that Towards AI post about schema drift."
"What has Andrej Karpathy published on Medium?"
"Which posts in my reading list are about Rust?"
"Which authors I follow post the most but I never read?"
"Save this post to my AI list." (Claude asks before each change)
Example
> What has Andrej Karpathy published on Medium?
● medium-reader - get_recent_posts (source: "@karpathy", limit: 3)
His three most recent Medium posts:
1. Software 2.0 (Nov 11, 2017): neural networks as a new way of writing software, not just another ML tool
2. AlphaGo, in context (May 31, 2017): what AlphaGo's win does and doesn't mean for AI
3. ICML accepted papers institution stats (May 24, 2017): which institutions had the most accepted ICML papersOther MCP clients
install covers Claude Code. For other clients, point them at dist/cli.js with an absolute path. Log in with node dist/cli.js login first either way.
Add to claude_desktop_config.json (Settings → Developer → Edit Config):
{
"mcpServers": {
"medium-reader": {
"command": "node",
"args": ["/absolute/path/to/medium-reader-mcp/dist/cli.js"]
}
}
}Add to ~/.cursor/mcp.json:
{
"mcpServers": {
"medium-reader": {
"command": "node",
"args": ["/absolute/path/to/medium-reader-mcp/dist/cli.js"]
}
}
}Add to .vscode/mcp.json in a workspace, or to your user MCP configuration:
{
"servers": {
"medium-reader": {
"type": "stdio",
"command": "node",
"args": ["/absolute/path/to/medium-reader-mcp/dist/cli.js"]
}
}
}claude mcp add --scope user medium-reader -- node /absolute/path/to/medium-reader-mcp/dist/cli.jsDaily digest with Hermes Agent
hermes/ contains a skill for Hermes Agent that turns this server into a scheduled Medium digest. Each morning it collects new posts from your Following feed and from "For you", filters out clickbait, has subagents read the most promising 20–25 in full, and sends one message with three sections: Following, Medium's top picks (positions 0–25 of "For you") and personal recommendations (positions 25–100). The top posts are flagged ⭐ "Read in full", with a two-line summary and why they're worth reading. The design follows the findings in How Medium's feeds behave.
Setup
Build the server on your machine (
npm ci && npm run build). Copydist/,package.jsonandpackage-lock.jsonto a directory the Hermes container can see (for example$HERMES_HOME/mcp/medium-reader-mcp, which is/opt/data/mcp/medium-reader-mcpinside the official image), and install the runtime dependencies there:npm ci --omit=dev --omit=optionalNode 20 or later works, including the Node 26 in the Hermes image.
Log in on a machine with a browser (
node dist/cli.js login), then copy~/.config/medium-reader/auth.jsoninto a directory on the Hermes host, for example$HERMES_HOME/mcp/medium-reader-home/. Keep it at owner-only permissions.Register the server in Hermes's
config.yaml:mcp_servers: medium-reader: command: node args: ["/opt/data/mcp/medium-reader-mcp/dist/cli.js"] env: MEDIUM_READER_HOME: /opt/data/mcp/medium-reader-homeInstall the skill: copy
hermes/SKILL.mdto$HERMES_HOME/skills/productivity/medium-digest/SKILL.md, andhermes/medium_digest_start.shto$HERMES_HOME/scripts/. Optionally, copyhermes/interests.example.mdtoSTATE_DIR/interests.mdand edit it (see below).Edit the Settings block at the top of
SKILL.md:STATE_DIR,TIMEZONE,MAX_PARALLELand theREAUTHmessage.Restart Hermes and schedule it. Cron times are in the Hermes host's local time:
hermes cron create "0 7 * * *" "Run the medium-digest skill and deliver the digest." \ --name medium-digest --skill medium-digest --script medium_digest_start.sh --deliver discord:<channel-id> hermes cron run <job-id> # try it once nowRun
hermes croncommands as the user the gateway runs as (docker exec -u hermes …in the official image), so the files it writes keep the right owner.
Customizing
What gets picked:
STATE_DIR/interests.mdis free text the skill reads on every run. Describe what you want more of. Its Skip section lists title patterns to drop entirely, for example "I tried N+ courses" or "passive income". Matching is by intent, not exact words. The digest ends with a count of skipped posts and names the authors who produce most of them, so you can mute them.Sizes: the numbers in the Procedure section (up to 10 picks from Following, 5 top picks, 10 from "For you", chunks of 5 per subagent) are plain instructions, so edit them directly.
Output format: the message template targets Discord Markdown. For Telegram, Slack or email, edit the template in the "Send the digest" step and the formatting rules under it.
Schedule and delivery: use
hermes cron edit <job-id> --schedule "…"or--deliver ….
Things to know
Tool results over about 50,000 characters don't reach the model. Hermes saves them to a file the model can't parse, and cron runs can't run scripts to help. That's why the skill asks for results in smaller pages. Keep that in mind if you raise the limits.
"For you" is only read to position 150. Paging to the end of that list (about 1,000 posts) makes Medium replace the list your homepage shows.
State: each run records what it reported in
STATE_DIR/state.json, so posts never repeat. A run that fails doesn't save state, so the next run covers the same period.Read-only: the skill never uses the tools that change your account.
Cost: the first run made 34 model calls and took about 12 minutes on Claude Sonnet, most of it the subagents reading posts in full. Some of that was working around results that were too large, which the current skill avoids.
Your own account: this server uses Medium's undocumented web API with your session cookies. A daily digest is light, read-only use, but if Medium objects to automated access, it's your account at risk.
Tools
Authors can be given as @username or a profile URL; publications by name, slug (javarevisited), or URL, including custom domains (https://pub.towardsai.net). Posts can be any Medium link, including custom domains, or the post's hex id.
Reading
Tool | What it returns |
| Whether you're logged in, as whom, and whether the account is a Medium member |
| Your Following feed (default) or For you, newest first. |
| A full post as Markdown (or |
| Latest posts from one author or publication, with a cursor for paging back |
| Keyword search across Medium |
| Authors or publications you follow. |
| Your reading list and named lists, with item counts |
| The posts in one of those lists |
| Posts you've read, most recently read first. Medium gives no read date per post. Useful for asking which follows you actually read |
Account changes
Tool | What it does |
| Follow or unfollow an author or publication. An ambiguous name lists the matches instead of guessing |
| Hide an author's or publication's posts from your feeds, including an author's posts in publications you follow. Private |
| Add a post to, or remove it from, your reading list or a named list |
| Clap for a post (never past Medium's 50-per-post limit), or take your claps back |
The reading tools are marked read-only. The rest are marked as changing your account, so MCP clients ask before running them. unfollow, remove_from_list and undo_clap are also marked destructive. After each change the server checks with Medium and reports what actually happened; doing something that's already done (following someone you follow, saving a saved post) changes nothing.
Follows and claps are visible to the author, and named lists are public. Mutes are private.
Logging in
Medium has no API keys or OAuth for readers, so the server uses your normal web session.
Browser login (default).
loginopens Chrome or Edge on Medium's sign-in page. Sign in however you normally do: an emailed link or code, Google, Apple, and so on. The session is captured, checked with Medium, and saved as soon as you're in. The login window keeps its own browser profile, so when the session expires (after about a year) runningloginagain usually finishes without typing anything.Paste.
login --pasteis for machines without a display. Copy thesidanduidcookies from your browser's DevTools (Application → Cookies → medium.com); Medium ignoressidon its own. ACookie:header (sid=…; uid=…), a Cookie-Editor JSON export, andcookies.txtall work.login --stdinreads the same formats from a pipe.No restart needed. The server re-reads the session on every call, so after
loginthe next request just works.
If Medium emails you a sign-in link, paste it into the address bar of the windowlogin opened. Clicking it opens your normal browser instead.
The login window must be a normal, visible window: Medium's Cloudflare protection blocks headless browsers.
Command | What it does |
| Browser login. Add |
| Shows the logged-in account, membership, and whether the session still works |
| Deletes the saved session. |
| Registers the server with Claude Code. |
Variable | Purpose |
| Session cookie values. Override the saved session, for containers or CI |
| A full |
| Config directory (default |
| A Chromium-based browser for |
Privacy and security
Where the session goes. The
sidanduidcookies are only ever sent tomedium.com. Posts on custom domains are fetched from medium.com by id, so those domains never see your session.What's stored. The session is saved to
~/.config/medium-reader/auth.jsonwith owner-only permissions (600), next to the login browser profile. Nothing is stored in this repository, and.gitignoreexcludes session files in case you copy them in.What leaves your machine. Requests go only to Medium. There's no analytics or telemetry. What Claude does with the content it reads is governed by your MCP client.
Reading history. Reading a post through this server doesn't add it to your Medium reading history.
Dependencies.
package-lock.jsonpins every dependency to an exact version and integrity hash. Install withnpm cifor a reproducible install.
How Medium's feeds behave
Findings from probing Medium's GraphQL API with this server's session in September 2026. They come from one account on one day, so treat them as observations rather than documented behaviour; Medium can change any of this without notice.
"For you" is a fixed list of about 1,000 posts
Medium builds the list once and keeps serving it. The paging cursor is a
sourceID (a UUID naming the list) plus an offset (to: 25, 50, … 975). Three fetches in a row returned the same 50 posts in the same order.Paging past the end builds a new list. After about 39 pages of 25, the next page comes from a new
source, and later fetches, including the first page, use it. The new list is mostly the same posts reordered: a second list added only 15 posts not in the first, and the first 300 of a third added none. Going deeper reshuffles about the same 1,000 candidates rather than reaching older posts.Posts range up to about a year old: median 7 days, a quarter older than 30 days, 5% older than about 3 months, and the oldest 356 days.
Heads-up: paging to the end of "For you" rebuilds the list your homepage shows.
get_feedreturns at most 100 posts per call, so this only happens if you keep followingnextCursorabout ten times.Not measured: whether a list also expires after some time without anyone paging to its end.
The order means something, but the top isn't "most like you"
All 975 posts of one list, compared by position. "Read" means the author or publication appears in the account's reading history.
Positions | Median age (days) | Median claps | Author you follow | Author you've read | Publication you've read |
0–25 | 22 | 1,554 | 16% | 32% | 36% |
25–100 | 8 | 374 | 32% | 47% | 36% |
100–250 | 11 | 411 | 24% | 47% | 32% |
250–500 | 9 | 206 | 18% | 37% | 46% |
500–750 | 7 | 168 | 8% | 18% | 45% |
750–975 | 4 | 142 | 1% | 4% | 44% |
The share of member-only posts (about 75–85%) and median reading time (5–8 minutes) are about the same at every depth.
Positions 0–25 are popular, proven posts spread across your topics. They're older, with 4–10 times the claps of anything deeper. The listed reasons show deliberate variety: nine topics followed ("Because you follow Startup", "…Education", "…Humor", …) got one post each, alongside "Selected for you" and a few "From your network".
Positions 25–250 are the most personal part. Here are the highest shares of authors you follow and authors you've actually read.
Positions 500 and beyond are fresh, low-clap posts. They're increasingly there because of network activity ("Someone clapped", "Someone responded"), and by the end almost none are from authors you've read.
So to find what a reader would actually pick, positions 25–250 matter more than the first page. To see what Medium is promoting to everyone, look at the first page. Each item's reason field (reasonString in GraphQL) says why it was included.
The Following feed
It's all posts from authors and publications you follow, roughly newest first, each tagged
PUBLISHED_BY_USERorPUBLISHED_BY_COLLECTION. On the test account about 94% came through publications, from 190 posts a day, so a handful of high-volume publications made up most of the feed.Reading a post doesn't remove it from the feed.
Unfollowing a publication didn't remove posts already in the feed. Muting worked straight away, and muting an author also hides their posts that come through publications you still follow. This is the only way to cut prolific writers out of a publication you want to keep.
"I'm not interested in this story" (
SHOW_LESS) doesn't remove the post from the Following feed. The web app only hides it on the page. Medium describes it as a recommendations signal, and its effect on "For you" can't be seen until the list is rebuilt.
Reproducing this
get_feed (feed: "for_you"), list_following and get_reading_history return everything used here: each post's author, publication, claps, publication date and reason. CLAUDE.md has the GraphQL details: the operations, how paging works, and what each field means.
Troubleshooting
Symptom | Fix |
"Not logged in" or "session was rejected" | Run |
A member-only story shows "Only a preview was returned" | The account isn't a Medium member, or the session expired. |
"Cloudflare protection blocked the request" | Usually temporary; wait a minute. If it persists, Medium has changed its bot rules; please open an issue. (Older versions of this server were blocked on every request under Node 26; update to fix that) |
The server doesn't appear in | Restart Claude Code. New servers are only loaded when a session starts |
| Install Chrome, set |
The server stopped starting after a Node upgrade |
|
Development
npm ci
npm test # vitest against a fake GraphQL endpoint; no network, no account needed
npm run typecheck
npm run build # compiles src/ to dist/src/
cli.ts entry point: serve, login, status, logout, install
server.ts MCP tool definitions
format.ts Medium's paragraph model → Markdown
auth/credentials.ts session storage; parses pasted cookies in any format
auth/login.ts browser and paste login
medium/http.ts GraphQL client: cookies, Cloudflare detection, retries
medium/api.ts queries, feed, posts, follows, lists, claps
test/ one file per module, plus an in-memory MCP client testCLAUDE.md records how Medium's GraphQL API actually behaves, including the fields that look right but aren't and how to find new queries. Read it before changing anything under src/medium/.
Disclaimer
An independent project, not affiliated with or endorsed by Medium. It uses Medium's undocumented web endpoints, which can change without notice. Use it with your own account, and within Medium's Terms of Service.
License
MIT © 2026 Bill Baran. Use, modify, and share it freely; keep the copyright notice.
Available Tools
14 toolsauth_statusMedium auth statusARead-only
Check whether a Medium session is configured and still valid, which account it belongs to, and whether it has a Medium membership (needed for member-only posts).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description adds behavioral context by stating it checks whether the session is 'still valid' and which account it belongs to, implying session expiry and account association. It does not contradict annotations and adds detail about the membership check, which is useful beyond the read-only flag.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured sentence that front-loads the verb 'Check' and packs all relevant checks into a compact list with a parenthetical clarification ('needed for member-only posts'). Every phrase adds value, with no redundant or filler words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter status tool, the description covers the essential decision factors: configuration, validity, account identity, and membership. It does not specify the return format, but the absence of an output schema and the simple status-check nature make this acceptable; the agent can infer the result from the described checks.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters and schema description coverage is trivially 100%. With no parameters to document, the baseline is 4; the description appropriately focuses on the tool's outcome rather than inputs, and there is nothing further it needs to clarify about parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses the specific verb 'Check' and names the exact resource (Medium session/account) and the four things it verifies: configuration, validity, account identity, and membership. This clearly distinguishes it from sibling tools like read_post or follow, which perform actions rather than report status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context by explaining that membership is needed for member-only posts, implicitly telling the agent when this check is useful. It does not explicitly name when-not scenarios or alternative tools, but no sibling tool competes with this status check, so the guidance is adequate though not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
clapClap for a postA
Clap for a post (visible to its author). Medium allows 50 claps per reader per post in total; this refuses to go past that. Only use when the user asks. undo_clap takes them back.
| Name | Required | Description | Default |
|---|---|---|---|
| post | Yes | Post URL (any Medium or custom-domain link) or the post's hex id. | |
| count | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate this is a mutating, non-idempotent operation. The description adds genuinely useful behavioral context beyond the annotations: the 50-clap per-reader limit and that the tool 'refuses to go past that.' This helps set expectations for side effects and edge cases without contradicting any annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler. The core action is front-loaded, the key behavioral constraint (50 claps) is stated succinctly, and the alternative tool is mentioned in one short phrase. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter tool with no output schema, the description covers the essential action, a behavioral limitation, and the reverse operation. It doesn't discuss error cases or authentication, but annotations and the schema already provide the safety profile and parameter constraints. It is complete enough for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 50% (only 'post' is described in the schema), so the description should compensate for the undocumented 'count' parameter. It mentions the 50-clap ceiling, which relates to count's maximum, but it doesn't explicitly state that 'count' is the number of claps to give. The description adds partial value but doesn't fully clarify parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Clap for a post') and the resource (a post), plus a notable consequence (visible to its author). It also explicitly distinguishes itself from the sibling undo_clap, making the tool's purpose and scope immediately unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit activation condition ('Only use when the user asks') and names the alternative for reversing the action ('undo_clap takes them back'). This is direct, practical guidance that tells an agent exactly when to invoke this tool versus the sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
followFollowAIdempotent
Follow an author or publication. Does nothing if already following. Only use when the user explicitly asks. If the name is ambiguous the candidates are returned; ask the user which one they mean.
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | An author ("@username" or profile URL) or publication (name, slug like "javarevisited", or URL like "https://pub.towardsai.net"). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide idempotentHint=true, so 'Does nothing if already following' reinforces but adds specific side-effect behavior. The description also discloses that ambiguous names return candidates, which is valuable because no output schema exists. It adds context beyond the structured hints without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, each earning its place: the core action, idempotence, usage restriction, and ambiguity handling. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter, low-complexity tool, the description covers the key agent needs: what to do, when to do it, and how to handle ambiguity. It does not state the success response format, but the absence of an output schema makes this a minor gap rather than a blocking one.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides 100% description coverage for the target parameter, including formats for authors and publications. The tool description itself adds no additional parameter meaning, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Follow an author or publication.' This clearly distinguishes the tool from siblings like unfollow and save_to_list, and clarifies what 'follow' means.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit guidance: 'Only use when the user explicitly asks' — a clear when-to-use condition. It also explains what to do in the ambiguous-name case. It does not name alternatives, but the restriction to explicit user intent effectively excludes auto-following.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_feedGet Medium feedARead-only
The user's home feed. "following" (default) is posts from the authors and publications they follow; "for_you" is Medium's recommendations. Pass nextCursor back as cursor for more.
| Name | Required | Description | Default |
|---|---|---|---|
| feed | No | following | |
| limit | No | ||
| since | No | Only posts after this point: an ISO date ("2026-09-01") or relative ("7d", "48h"). | |
| cursor | No | nextCursor from a previous call. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint and openWorldHint annotations already cover the safety and dynamic nature of the operation. The description adds value beyond those by explaining the two feed modes and the pagination contract ('Pass nextCursor back as cursor'), which are behavioral details an agent needs to use the tool correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler: the first defines the resource, the second explains the input variants and pagination. It is front-loaded with the main concept and every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the core purpose, feed variants, and pagination, but with no output schema it does not describe the shape of feed items or how to identify a post for subsequent operations. The resource and parameters are clear enough for invocation, but an agent may need more context about the response.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 50% (since and cursor are documented). The description adds meaning to the 'feed' enum and restates cursor usage, which is helpful. However, it does not add anything for 'limit' or expand on the 'since' format, leaving the agent to rely solely on the schema for those.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states this returns the user's home feed and defines the two feed variants, which makes the resource specific. It does not explicitly contrast with siblings like get_recent_posts or search_posts, so it stops short of full differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains that 'following' returns posts from followed authors/publications and 'for_you' returns recommendations, which implies how to choose between them. However, it gives no guidance on when to use get_feed versus sibling tools such as get_recent_posts or search_posts, so the tool-selection guidance is only implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_listGet list postsARead-only
Posts saved in the reading list or one of the user's named lists, most recently added first.
| Name | Required | Description | Default |
|---|---|---|---|
| list | No | "reading-list" (default) or the name / id of one of the user's lists, as shown by list_reading_lists. | reading-list |
| limit | No | ||
| cursor | No | nextCursor from a previous call. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the description doesn't need to cover those. It does add the ordering (most recently added first), which is useful, but it omits details like pagination behavior via cursor or error handling when a list is not found. The added context is minimal but not contradictory.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, focused sentence that states the primary action and ordering. It's efficient with no redundancy and front-loads the core purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list retrieval tool with open-world semantics and no output schema, the description is minimally sufficient but lacks usage guidance and pagination details. The schema covers parameters well, so the main gap is absence of when-to-use context, which would round out completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 67% (list and cursor have descriptions, limit does not). The description adds no parameter-specific information beyond what's already in the schema. Since coverage is above 50%, the baseline of 3 is appropriate; the description doesn't compensate for the undocumented limit parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves posts from a reading list or named lists, ordered by most recent first. This distinguishes it from siblings like get_feed, get_recent_posts, and search_posts by identifying the specific resource (lists) and the ordering behavior.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to choose this tool over alternatives. It doesn't compare with get_feed or get_recent_posts, nor does it mention prerequisites like needing a list name from list_reading_lists. Usage context is entirely implied, not explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recent_postsGet recent postsARead-only
Latest posts from one author or publication. Pass nextCursor back as cursor to page back.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| cursor | No | nextCursor from a previous call. | |
| source | Yes | An author ("@username" or profile URL) or publication (name, slug like "javarevisited", or URL like "https://pub.towardsai.net"). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, covering safety and world-scope. The description adds useful behavioral context beyond annotations: it establishes the 'latest posts' ordering and discloses pagination behavior via 'Pass nextCursor back as `cursor` to page back.' This meaningfully enriches the agent's understanding of call behavior without repeating annotation data.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences carry all essential information: the first declares the tool's purpose, the second gives the pagination contract. There is zero filler or redundancy. The most important information is front-loaded, making it easy for an agent to parse quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter, read-only list tool with no output schema, the description covers the core invocation requirements: source scope and pagination. It doesn't describe the shape of returned posts, but the name and title 'Get recent posts' make that implicit. Given annotations cover the safety profile and schema covers parameter details, the description is sufficiently complete for correct calling.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 67%: `source` and `cursor` already have detailed descriptions, while `limit` has none. The description adds only marginal value to parameter meaning—mostly restating cursor and pagination semantics. It does not clarify the `limit` parameter, which remains undocumented beyond its type/default/max/min, so a baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource: 'Latest posts from one author or publication.' This clearly identifies what the tool does and narrows scope to a single source, which helps distinguish it from broader tools like get_feed or search_posts. However, it doesn't explicitly name sibling tools or contrast its behavior, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'from one author or publication' provides clear context for when to use this tool – when you need posts from a known, specific source. It does not explicitly mention alternatives or exclusions, but the scope is unambiguous. The pagination instruction adds a clear usage note about handling result sets, so the intended use case is well implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_followingList who you followARead-only
Authors (default) or publications the logged-in user follows, with the total count.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | users | |
| limit | No | ||
| cursor | No | nextCursor from a previous call. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the description's job is lighter. It adds useful behavioral context by scoping results to the logged-in user and mentioning the total count in the response. It does not contradict the annotations, though it does not disclose pagination behavior beyond what the schema's cursor description already provides.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence that front-loads the primary choice (authors vs publications), states the scope (logged-in user), and includes the notable response detail (total count). There is no filler or redundant wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list endpoint with no required parameters, the description plus annotations and schema-provided cursor/limit constraints are largely sufficient. The lack of an output schema is partly mitigated by mentioning the total count, though item-level response fields are not described.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description clarifies the key enum parameter by mapping 'users' to 'Authors' and noting the default. However, schema description coverage is only 33%, and the description does not add meaning for limit or further explain cursor beyond the schema's 'nextCursor from a previous call' note, so compensation is only partial.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('list') and a precise resource scope: authors or publications followed by the logged-in user. It also adds the total-count detail, making the tool's purpose unmistakable and distinguishing it from siblings like get_feed or list_reading_lists.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use guidance or mention of alternatives such as get_feed or get_list. Usage is implied by the description's phrasing but not spelled out, so an agent must infer when this tool is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_reading_listsList reading listsARead-only
The user's reading list (saved posts) and their named lists, with item counts.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safe read-only nature is covered. The description adds useful context by specifying both the default reading list and named lists, plus item counts, which helps set expectations for the output. It does not mention ordering, pagination, or whether empty lists are included, but for a simple read-only listing this is acceptable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, focused sentence that conveys the scope and key output detail without wasted words. It is front-loaded with the main object ('the user's reading list') and ends with the distinguishing count detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only listing tool with no output schema, the description adequately explains what the agent will receive: the saved-posts reading list and named lists with item counts. It could be more explicit about the exact return shape or whether the default list is included separately, but the essential information is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and schema coverage is 100%, so there is no parameter information burden on the description. The description appropriately avoids inventing parameter details and instead communicates what the result contains, which is the relevant semantic information here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the resource—the user's reading list and named lists—and specifies that item counts are included. It stops short of an explicit verb like 'returns' or 'lists', but the meaning is unambiguous. It also implicitly distinguishes itself from get_list by focusing on list overviews with counts rather than list contents.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given about when to use this tool versus alternatives such as get_list or get_feed. The description implies it is for viewing a summary of saved posts and named lists, but it provides no exclusions, prerequisites, or explicit routing to sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_postRead a postARead-only
Read a Medium post as Markdown. Member-only posts are returned in full when the logged-in account is a Medium member. Works for posts on custom domains too. Long posts are paged: pass start from the previous response to continue.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Post URL (any Medium or custom-domain link) or the post's hex id. | |
| start | No | Character offset into the body, for paging. | |
| format | No | markdown | |
| max_chars | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only/open-world behavior; the description adds meaningful behavioral context: member-only posts are fully returned only for members, custom domains work, and long posts are paged with start. It does not cover non-member behavior or max_chars effects, but the provided disclosures go beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise, front-loaded sentences: the core purpose comes first, then membership and domain caveats, then the paging mechanism. Every sentence contributes without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Without an output schema, the description does explain the return form (Markdown) and paging contract, which is helpful. But it omits the behavior of max_chars and the text format option, leaving important gaps for a four-parameter tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 50%, and the description adds meaning for start by explaining pagination and notes Markdown as the output format. However, max_chars is left completely unexplained and the format='text' option is not mentioned, so the description does not fully compensate for the schema gaps.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Read a Medium post') and output format ('as Markdown'), which distinguishes it from feed/list tools like get_feed or get_recent_posts. The additional scope notes about custom domains and member-only posts sharpen the purpose further.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage by URL and adds useful context about custom domains and membership, but it never names alternatives or says when not to use this tool versus siblings like search_posts or get_recent_posts. No explicit when/when-not routing is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_from_listRemove from listADestructiveIdempotent
Remove a post from the reading list (default) or one of the user's named lists. Only use when the user asks.
| Name | Required | Description | Default |
|---|---|---|---|
| list | No | "reading-list" (default) or the name / id of one of the user's lists, as shown by list_reading_lists. | reading-list |
| post | Yes | Post URL (any Medium or custom-domain link) or the post's hex id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, so the description doesn't need to restate those. It adds context about the default list and named lists, plus the user-intent condition. However, it doesn't describe side effects like behavior on missing posts or idempotency details, which are partially covered by annotations. With annotations present, this is moderate value.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with zero fluff. The core action is front-loaded ('Remove a post...'), and the usage condition is a separate concise sentence. Every word contributes to understanding when and how to use the tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple mutation tool with only two parameters and no output schema, the description covers the essential action, default scope, and user-intent condition. Annotations handle the destructive and idempotent profile, and the schema references list_reading_lists for list names. It doesn't explain edge cases, but nothing critical is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% – both parameters have detailed descriptions (post URL/hex id, list default and reference to list_reading_lists). The tool description adds no additional meaning to the parameters beyond what the schema already provides. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear, specific action: 'Remove a post from the reading list (default) or one of the user's named lists.' It distinguishes from sibling tools like save_to_list (opposite) and list_reading_lists (list names) by focusing on removal and specifying the default list. No ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Only use when the user asks,' which sets a clear usage boundary. It does not explicitly name alternatives or when-not to use, but the schema references list_reading_lists for list names, and the purpose itself implies when it's appropriate. This is clear context but lacks explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_to_listSave to listAIdempotent
Save a post to the reading list (default) or one of the user's named lists. Does nothing if it's already there. Only use when the user asks.
| Name | Required | Description | Default |
|---|---|---|---|
| list | No | "reading-list" (default) or the name / id of one of the user's lists, as shown by list_reading_lists. | reading-list |
| post | Yes | Post URL (any Medium or custom-domain link) or the post's hex id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate the tool is mutating and idempotent. The description adds concrete behavioral detail with 'Does nothing if it's already there' and the default-list behavior, which helps the agent predict outcomes without contradicting the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three short sentences with no filler. The key action, default behavior, idempotency, and usage guardrail are all front-loaded and each sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter tool with annotations and full schema coverage, the description is adequately complete. It covers the action, default, duplicate behavior, and the condition to invoke it; no critical operational details are missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both parameters. The description mainly restates the default list behavior and does not add material parameter-level detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Save') and a clearly defined resource (a post to a list). It also distinguishes itself from sibling tools like remove_from_list and list_reading_lists by explicitly stating the default reading list and named-list behavior.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use the tool ('Only use when the user asks') and explains the default and named-list targets. It does not explicitly name alternatives or when-not-to-use conditions, but the purpose is distinct enough among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_postsSearch MediumARead-only
Search all of Medium for posts by keyword. Pass nextCursor back as page for more results.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| limit | No | ||
| query | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only and open-world behavior. The description adds a non-obvious pagination contract: nextCursor must be passed back as page for subsequent results. This is useful behavioral context not present in the 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with purpose and followed by actionable pagination guidance. Every sentence earns its place with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Invocation-critical details are covered: read-only scope, keyword search, and pagination. Since there is no output schema, the description could say a bit more about what the response contains beyond nextCursor, but for a search tool this is largely sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It adds meaning for query (keyword) and page (pagination via nextCursor), but limit is never mentioned. The parameter names and defaults are somewhat self-explanatory, but coverage is only partial.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Search all of Medium for posts by keyword.' This clearly distinguishes it from sibling tools like get_feed and get_recent_posts, which are scoped or personalized rather than a global keyword search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context for when to use the tool: when the user wants a global Medium keyword search. It does not explicitly name alternatives or exclusions, but the 'all of Medium' scope makes the intended use distinct from feed/list/reading-list tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
undo_clapUndo clapsBDestructiveIdempotent
Remove all of the user's claps from a post. Only use when the user asks.
| Name | Required | Description | Default |
|---|---|---|---|
| post | Yes | Post URL (any Medium or custom-domain link) or the post's hex id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already indicate destructiveHint and readOnlyHint=false, so the description's 'Remove all' is consistent with those. It adds context that it affects the user's claps, which is useful, but it doesn't mention any side effects like irreversibility or permission requirements beyond what annotations imply. It adds some value but does not go beyond the annotation's baseline significantly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise, one sentence long, and front-loads the action. Every word is meaningful. It loses a point because it lacks any structural organization, but for its brevity it is well-formed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple with one parameter, no output schema, and annotations cover safety (destructive hint). The description tells the agent when to use it. It is adequate but could mention that it only removes claps made by the current user and any potential need for authentication, though that is likely implied by 'the user's claps'.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema covers the parameter 'post' with a clear description (URL or hex id), so the description adds no additional parameter semantics. With 100% schema coverage, the baseline is 3, and the description does not enhance it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (remove claps) and the resource (a post), and specifies it applies to 'the user's claps'. It is distinct from its sibling 'clap', which adds claps, and from other read/list tools. However, it does not explicitly name the sibling it contrasts with, so it misses the top score.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It says 'Only use when the user asks', which gives a clear trigger condition. However, it does not specify when NOT to use it or mention any alternatives, such as 'clap' for adding claps. The instruction is useful but lacks exclusionary guidance, making it adequate but not comprehensive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unfollowUnfollowADestructiveIdempotent
Unfollow an author or publication. Only use when the user explicitly asks. If the name is ambiguous the candidates are returned; ask the user which one they mean.
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | An author ("@username" or profile URL) or publication (name, slug like "javarevisited", or URL like "https://pub.towardsai.net"). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and destructiveHint=true, covering the mutation and destructive nature. The description adds valuable context: the ambiguity handling (candidates returned) and the explicit user request requirement. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences with zero redundancy. The core action is front-loaded, followed by critical usage and ambiguity guidance. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter tool with no output schema and annotations covering the safety profile, the description is complete. It covers what, when, and how to handle ambiguity, leaving no critical gap for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameter is fully documented. The description adds behavioral meaning beyond the schema by explaining that ambiguous names return candidates for user disambiguation, which enriches the parameter's semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Unfollow an author or publication') and clearly distinguishes the action from siblings like 'follow' and 'list_following'. The scope is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use ('Only use when the user explicitly asks') and handles ambiguity by instructing to ask the user. It does not explicitly list alternatives or exclusion criteria, but the condition is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
14 tool updates
v0.1.0- First observed
auth_status - First observed
clap - First observed
follow - First observed
get_feed - First observed
get_list - First observed
get_recent_posts - First observed
list_following - First observed
list_reading_lists - First observed
read_post - First observed
remove_from_list - First observed
save_to_list - First observed
search_posts - First observed
undo_clap - First observed
unfollow
TDQS
Scored across 14 tools
Most tools target distinct actions and resources, but get_list and list_reading_lists overlap somewhat since both involve reading lists, and get_feed vs get_recent_posts could be confused by name alone. Descriptions generally resolve the boundaries.
Most names follow a clear verb_noun pattern like get_feed, search_posts, save_to_list, and remove_from_list. Minor deviations exist with auth_status lacking a verb and read_post/clap/undo_clap using different verb styles, but the pattern is still predictable.
14 tools is well-scoped for a Medium reader/engagement server, covering reading, searching, following, list management, and clapping without unnecessary redundancy. Each tool earns its place.
The surface covers core reading workflows: feeds, posts, search, author/publication posts, following, reading lists, and clapping. Minor gaps exist such as no named-list creation/deletion and no direct user/publication profile lookup, but these are not critical for the stated reader-oriented purpose.
Maintenance
Related MCP Connectors
Browser MCP for logged-in tasks. Uses your Chrome — credentials stay local. Zero-token replay.
OAuth MCP for Google, Meta, X, LinkedIn, Reddit, TikTok, GSC, GA4, WordPress and GHL.
MCP server connecting AI agents to 100+ apps (Gmail, Slack, Notion, GitHub) via one-click OAuth.
Connect AI agents to Filepad workspaces through OAuth MCP.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables claude.ai to connect to GitHub MCP using OAuth, providing full toolset for repository, issue, PR, Actions, and gist operations.-
- AlicenseNot gradedqualityBmaintenanceEnables MCP clients like Codex and Claude Code to securely read and manage a personal Cronometer account, including food logs, nutrient summaries with missing-data awareness, food search, biometrics, and export analysis.MIT
- AlicenseNot gradedqualityCmaintenanceEnables MCP clients like Claude to securely read your own Cronometer nutrition and biometric data using your account credentials, with read-only access and optional human-readable output.MIT
- AlicenseNot gradedqualityCmaintenanceEnables MCP clients to act as an authenticated Overleaf user, letting them access and manipulate projects through Overleaf's web API.1GPL 3.0