Skip to main content
Glama
Anthonyeef

fanfou-mcp

by Anthonyeef

fanfou-mcp

A Model Context Protocol server for Fanfou (饭否). 让 Claude、Cursor 等 MCP 客户端直接读写你的饭否时间线。

fanfou-mcp exposes the Fanfou REST API as MCP tools so that an AI assistant can read your timeline, search statuses, look up users and (optionally, with explicit confirmation) post, delete, favorite and follow.

It ships with two transports sharing the same tool set:

Transport

Entry point

Typical use

stdio

server.py

Local MCP clients (Claude Desktop, Cursor, …) launching the server as a subprocess

Streamable HTTP

http_app.py (ASGI)

Remote / serverless hosting, e.g. on Vercel — single-user (one bearer token) or multi-user (each user authorizes their own Fanfou account)

Python ≥ 3.12, built on the official mcp Python SDK (FastMCP). The Fanfou client itself uses only the standard library (no requests / oauthlib).


⚠️ Before you start: you need your own Fanfou app key

Fanfou has not accepted new API application registrations since 2020 (the developer program is whitelist-only). 饭否自 2020 年起不再开放新应用申请,新注册的应用无法通过审核,调用 API 会返回 401。

This project therefore does not include any consumer key. To use it you must bring:

  1. A consumer key / secret of a Fanfou app that has already been approved (审核通过), and

  2. An OAuth access token / secret for your account, obtained with that app (see OAuth authorization).

An app whose review status is "rejected" (已驳回) or pending will be able to complete the OAuth handshake, but every API call (even /help/test.json) will fail with 401 参数错误!.


Related MCP server: twscrape-twitter-mcp

Tools

Read-only tools (11)

Tool

Description

verify_credentials

Return the authenticated account

home_timeline

Home timeline (statuses from people you follow); count 1–60, since_id, max_id, page

user_timeline

A user's statuses (user_id empty = yourself)

mentions

Statuses mentioning you

public_timeline

Latest public statuses

search_public_timeline

Keyword search across public statuses (a b = AND, a|b = OR)

search_user_timeline

Keyword search within one user's statuses

get_status

One status by id

get_context

Conversation context (reply chain) of a status

get_user

A user's profile (user_id empty = yourself)

favorites

A user's favorited statuses

Write tools (4)

Tool

Description

post_status

Post a status; supports in_reply_to_status_id and repost_status_id

delete_status

Delete one of your own statuses

favorite

Favorite (action="create") or unfavorite (action="destroy") a status

friendship

Follow (action="create") or unfollow (action="destroy") a user

Safety rails for write tools:

  • Every write tool requires confirm=true. Without it, nothing is sent and the tool returns an error (post_status also returns a preview of the text). Tool descriptions instruct the model to only set confirm=true after the user has explicitly approved the exact action in chat.

  • Set FANFOU_MCP_READONLY=1 to not register the write tools at all. This is the default for the HTTP server (http_app.py); the stdio server defaults to 0 (write tools available).

Responses are trimmed to the useful fields (id, text, author, timestamps, photo URL, repost, …) to keep the model's context small. API errors are returned as {"error": "..."} rather than raised.


Architecture

fanfou_api.py   Minimal Fanfou OAuth 1.0a client (HMAC-SHA1 signing, stdlib urllib)
creds.py        Credential resolution: app key from env + per-request user token; multi-user token storage
kv.py           Tiny KV client: Vercel KV / Upstash Redis REST API (stdlib), or in-memory for local dev
tools.py        FastMCP instance and all 15 tool definitions; READONLY switch
server.py       stdio entry point            ->  mcp.run()
http_app.py     Streamable HTTP ASGI app     ->  POST /mcp, GET /healthz, bearer auth,
                                                 GET /authorize, GET /callback, POST /revoke (multi-user)

Helper scripts:

File

Purpose

run.sh

Launch the stdio server via uv, optionally loading credentials from local files (see below)

dev_http.sh

Serve http_app:app locally with uvicorn on 127.0.0.1:${PORT:-8765}

test_client.py

stdio smoke test: list tools, call a few read tools (--all for more)

test_http_client.py

HTTP smoke test against a local or remote /mcp endpoint

test_multiuser.py

Multi-user end-to-end test (OAuth routes, per-user tokens, revoke)

dev/mock_upstash.py

Local stand-in for the KV REST API, for testing

dev/mint_token.py

Issue a personal token for an existing Fanfou access token (admin / migration)

Notes on the HTTP app:

  • Stateless, JSON responses (stateless_http=True, json_response=True) and a fresh StreamableHTTPSessionManager per request, so it does not depend on ASGI lifespan — safe for serverless.

  • creds.current_principal / creds.current_user_token are ContextVars set per request by the auth layer. In multi-user mode they carry the calling user's Fanfou token (looked up in KV); with the admin token, or over stdio, the owner token from env is used. Tools never see bearer tokens.


Implementation notes (Fanfou quirks)

These cost real debugging time; they are documented here so you don't have to rediscover them.

  1. OAuth 1.0a: sign http://, request https://. Requests are sent to https://api.fanfou.com/..., but the OAuth signature base string must use the http:// URL. Signing the https URL fails with Invalid signature. Expected basestring is GET&http%3A%2F%2F.... 签名 base string 必须用 http://,实际请求走 https://。

  2. The API gateway rejects curl/* User-Agents. api.fanfou.com answers an nginx 404 for any curl/* UA, so the client sends its own User-Agent. Keep this in mind when testing by hand with curl (pass -A something-else).

  3. Requests use mode=lite where supported to get smaller payloads.

  4. Percent-encoding follows RFC 3986 (quote(s, safe="~")) for both the signature and the request.


Configuration

Variable

Required

Description

FANFOU_API_KEY

yes

Consumer key of an approved Fanfou app

FANFOU_API_SECRET

yes

Consumer secret

FANFOU_OAUTH_TOKEN

single-user

User access token (owner account; optional in multi-user mode)

FANFOU_OAUTH_TOKEN_SECRET

single-user

User access token secret

MCP_AUTH_TOKEN

HTTP only

Admin / owner bearer token (Authorization: Bearer <token>); acts as the env account

KV_REST_API_URL / KV_REST_API_TOKEN

multi-user (option A)

Vercel KV / Upstash Redis REST credentials. Also accepts UPSTASH_REDIS_REST_* and UPSTASH_KV_REST_API_* (custom UPSTASH prefix)

REDIS_URL

multi-user (option B)

Redis URL (Vercel Marketplace Redis injects this; rediss:// TLS ok). UPSTASH_REDIS_URL also accepted. Used only when REST env vars are unset

FANFOU_MCP_PUBLIC_URL

multi-user

Public origin used to build the OAuth callback, e.g. https://<your-project>.vercel.app. Falls back to the request's Host header

FANFOU_MCP_KV

no

memory = in-process KV for local dev (single process, lost on restart)

FANFOU_MCP_READONLY

no

1 = don't register write tools. Default 0 for stdio, 1 for HTTP

FANFOU_MCP_ALLOW_NOAUTH

no

1 = allow HTTP requests without bearer when MCP_AUTH_TOKEN is unset. Local dev only — never in production

Optional convenience for run.sh / dev_http.sh (environment variables always win):

  • ~/.fanfou_app — an INI-like file with sections headed # <app name> containing FANFOU_API_KEY=... / FANFOU_API_SECRET=...; select the section with FANFOU_APP_SECTION (default default).

  • FANFOU_TOKEN_FILE (default ~/.fanfou_token) — a file containing FANFOU_OAUTH_TOKEN=... / FANFOU_OAUTH_TOKEN_SECRET=... lines.

Never commit these files or a .env (both are git-ignored).


Running locally (stdio)

Requires uv.

git clone https://github.com/Anthonyeef/fanfou-mcp.git
cd fanfou-mcp
uv sync

export FANFOU_API_KEY=<consumer_key>
export FANFOU_API_SECRET=<consumer_secret>
export FANFOU_OAUTH_TOKEN=<access_token>
export FANFOU_OAUTH_TOKEN_SECRET=<access_token_secret>

uv run python test_client.py --all     # smoke test

MCP client configuration

Claude Desktop (claude_desktop_config.json), Cursor (~/.cursor/mcp.json) and most other clients accept:

{
  "mcpServers": {
    "fanfou": {
      "command": "uv",
      "args": ["run", "--directory", "/absolute/path/to/fanfou-mcp", "python", "server.py"],
      "env": {
        "FANFOU_API_KEY": "<consumer_key>",
        "FANFOU_API_SECRET": "<consumer_secret>",
        "FANFOU_OAUTH_TOKEN": "<access_token>",
        "FANFOU_OAUTH_TOKEN_SECRET": "<access_token_secret>",
        "FANFOU_MCP_READONLY": "1"
      }
    }
  }
}

Drop FANFOU_MCP_READONLY (or set it to 0) if you want the write tools. Alternatively point command at /absolute/path/to/fanfou-mcp/run.sh and let it load credentials from local files.

Local HTTP server

export MCP_AUTH_TOKEN=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
./dev_http.sh                                   # serves http://127.0.0.1:8765/mcp
uv run python test_http_client.py               # in another shell, same env

Remote deployment (Vercel)

pyproject.toml declares the ASGI entry point for Vercel's Python runtime:

[tool.vercel]
entrypoint = "http_app:app"
  1. Create a project in your Vercel account/team. Framework preset: Python (not "Other"/null — with no preset Vercel expects functions under /api). Root directory: this repo.

  2. Add environment variables (Production, mark as Sensitive): FANFOU_API_KEY, FANFOU_API_SECRET, FANFOU_OAUTH_TOKEN, FANFOU_OAUTH_TOKEN_SECRET, MCP_AUTH_TOKEN (a fresh random string), and optionally FANFOU_MCP_READONLY=1 (already the HTTP default). Do not set FANFOU_MCP_ALLOW_NOAUTH.

  3. Deploy: vercel deploy --prod from the repo, or connect the Git repository. Preview deployments sit behind Vercel Deployment Protection, so test against the production domain.

  4. Verify:

    curl https://<your-project>.vercel.app/healthz
    MCP_AUTH_TOKEN=<token> uv run python test_http_client.py https://<your-project>.vercel.app/mcp
  5. Connect a client that supports remote MCP servers:

    {
      "mcpServers": {
        "fanfou": {
          "url": "https://<your-project>.vercel.app/mcp",
          "headers": { "Authorization": "Bearer <MCP_AUTH_TOKEN>" }
        }
      }
    }

Endpoints: POST /mcp (MCP Streamable HTTP, stateless, JSON), GET /healthz (returns {"ok": true, "readonly": ...}). vercel.json requests the hkg1 region; Vercel may still run the function elsewhere — the Fanfou API has been reachable from US regions as well.

Security: with the single-user model, anyone holding MCP_AUTH_TOKEN acts as your Fanfou account. Treat it like a password and rotate it if leaked. Keep the remote server read-only unless you need writes.


Hosting a multi-user instance / 托管多用户实例

One deployment can serve many people: everyone connects to the same /mcp endpoint, but each person authorizes their own Fanfou account in the browser and gets a personal bearer token, so tools read their own timeline. 同一个实例服务多人,每人授权自己的饭否账号、拿到自己的个人令牌。

How it works:

  1. GET /authorize — the server requests a Fanfou request token (with oauth_callback=<public url>/callback), stores its secret in KV for 10 minutes, and redirects the browser to Fanfou's authorization page.

  2. The user logs in to Fanfou and approves the app.

  3. GET /callback — Fanfou redirects back; the server consumes the request-token secret (one-shot), exchanges it for the user's access token, calls verify_credentials, generates a random personal token (ffm_…, 256 bits) and shows it once, together with a ready-to-paste MCP client config.

  4. POST /mcp with Authorization: Bearer ffm_… — the server looks the token up in KV and runs the tools with that user's Fanfou token. Unknown or revoked tokens get 401.

  5. POST /revoke with the same bearer deletes the personal token.

Storage (Vercel KV / Upstash Redis, REST API):

Key

Value

TTL

fanfou-mcp:rt:<request_token>

request token secret

10 min, deleted on use

fanfou-mcp:user:<sha256(personal_token)>

{oauth_token, oauth_token_secret, fanfou_user_id, created_at}

none

Personal tokens are never stored in clear, only their SHA-256. The KV does hold users' Fanfou access tokens, so treat the KV credentials as secrets.

Setup on Vercel: attach either a KV / Upstash store (injects KV_REST_API_URL + KV_REST_API_TOKEN) or the official Redis Marketplace integration (injects REDIS_URL). Either one enables multi-user mode; REST is preferred when both are set. Then set FANFOU_MCP_PUBLIC_URL, keep FANFOU_API_KEY / FANFOU_API_SECRET (an approved app), and redeploy. MCP_AUTH_TOKEN + FANFOU_OAUTH_TOKEN[_SECRET] are optional and keep working as an admin/owner login. See DEPLOY.md.

Things to consider before opening an instance to others:

  • All users share one consumer key: Fanfou rate limits apply to that app, and abuse by one user can affect everyone. Make sure your use of the key complies with Fanfou's terms.

  • Keep the instance read-only (FANFOU_MCP_READONLY=1, the HTTP default).

  • Anyone holding a personal token can read that user's Fanfou (including protected statuses they can see).

Local test without a real KV:

python dev/mock_upstash.py 8079 &                       # fake KV REST API
export KV_REST_API_URL=http://127.0.0.1:8079 KV_REST_API_TOKEN=dev
export FANFOU_API_KEY=... FANFOU_API_SECRET=... FANFOU_OAUTH_TOKEN=... FANFOU_OAUTH_TOKEN_SECRET=...
export MCP_AUTH_TOKEN=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
./dev_http.sh &
uv run python test_multiuser.py                         # end-to-end checks
# or by hand: open http://127.0.0.1:8765/authorize in a browser, approve on Fanfou,
# then: MCP_AUTH_TOKEN=<the ffm_ token shown> uv run python test_http_client.py

Connecting as a user / 作为用户如何授权接入

If someone runs a hosted instance for you (e.g. https://<instance>):

  1. Open https://<instance>/authorize in your browser, log in to Fanfou and click approve. 打开授权链接,登录饭否并同意授权。

  2. You land on a page showing your personal token (ffm_…) and a config snippet. Copy it now — it is shown only once. 令牌只显示一次,请立即保存。

  3. Add the server to your MCP client:

    {
      "mcpServers": {
        "fanfou": {
          "url": "https://<instance>/mcp",
          "headers": { "Authorization": "Bearer <your personal token>" }
        }
      }
    }
  4. To disconnect: curl -X POST https://<instance>/revoke -H "Authorization: Bearer <your personal token>", and/or revoke the app's authorization in your Fanfou account settings. Lost the token? Just authorize again to get a new one.

The hosted instance is read-only: it can read your timeline, mentions, favorites and search, but cannot post, delete, favorite or follow on your behalf.


OAuth authorization (oob PIN)

Fanfou uses OAuth 1.0a. For a personal setup the simplest way to get an access token is the out-of-band (PIN) flow. 用 oob PIN 方式拿 access token:

  1. Request token — signed (consumer key/secret only, empty token secret) request with oauth_callback=oob:

    GET https://fanfou.com/oauth/request_token

    Response: oauth_token=<request_token>&oauth_token_secret=<request_token_secret>

  2. Authorize — open in a browser while logged in to Fanfou, and approve:

    https://fanfou.com/oauth/authorize?oauth_token=<request_token>&oauth_callback=oob

    Fanfou shows a PIN (verifier).

  3. Access token — signed with the request token/secret and oauth_verifier=<PIN>:

    GET https://fanfou.com/oauth/access_token

    Response: oauth_token=<access_token>&oauth_token_secret=<access_token_secret> → use them as FANFOU_OAUTH_TOKEN / FANFOU_OAUTH_TOKEN_SECRET.

The same quirks apply: sign the http://fanfou.com/oauth/... URL while sending the request over https, and don't use a curl/* User-Agent. A minimal standalone helper:

# oauth_pin.py — usage: python oauth_pin.py   (needs FANFOU_API_KEY / FANFOU_API_SECRET in env)
import base64, hashlib, hmac, os, secrets, time, urllib.parse as up, urllib.request as ur

CK, CS = os.environ["FANFOU_API_KEY"], os.environ["FANFOU_API_SECRET"]
q = lambda s: up.quote(str(s), safe="~")

def call(path, token="", token_secret="", **extra):
    p = {"oauth_consumer_key": CK, "oauth_nonce": secrets.token_hex(8), "oauth_signature_method": "HMAC-SHA1",
         "oauth_timestamp": str(int(time.time())), "oauth_version": "1.0", **extra}
    if token:
        p["oauth_token"] = token
    norm = "&".join(f"{q(k)}={q(v)}" for k, v in sorted(p.items()))
    base = "&".join(["GET", q(f"http://fanfou.com{path}"), q(norm)])          # sign http://
    key = f"{q(CS)}&{q(token_secret)}".encode()
    p["oauth_signature"] = base64.b64encode(hmac.new(key, base.encode(), hashlib.sha1).digest()).decode()
    hdr = {"Authorization": "OAuth " + ", ".join(f'{k}="{q(v)}"' for k, v in p.items()),
           "User-Agent": "fanfou-mcp-oauth/0.1"}
    with ur.urlopen(ur.Request(f"https://fanfou.com{path}", headers=hdr), timeout=20) as r:  # send https://
        return dict(up.parse_qsl(r.read().decode()))

req = call("/oauth/request_token", oauth_callback="oob")
print("Open and approve:\n  https://fanfou.com/oauth/authorize?oauth_token=%s&oauth_callback=oob" % req["oauth_token"])
pin = input("PIN: ").strip()
acc = call("/oauth/access_token", req["oauth_token"], req["oauth_token_secret"], oauth_verifier=pin)
print("FANFOU_OAUTH_TOKEN=%s\nFANFOU_OAUTH_TOKEN_SECRET=%s" % (acc["oauth_token"], acc["oauth_token_secret"]))

Store the printed values somewhere private (a password manager, a chmod 600 file, or your host's secret store). You can revoke the authorization from your Fanfou account settings at any time.


Roadmap

  • KV/Redis-backed per-user tokens + web OAuth callback flow, enabling multi-user hosting

  • MCP OAuth (authorization-server metadata) so clients can connect without pasting a token

  • Photo upload (/photos/upload.json), direct messages, follower/friend lists

Contributions are welcome — please open an issue or PR.

Acknowledgements

License

MIT © Anthonyeef

Available Tools

15 tools
delete_statusA

Delete one of the user's own statuses. WRITE ACTION: only call after the user has explicitly confirmed this exact action and content in chat. Requires confirm=true.

ParametersJSON Schema
NameRequiredDescriptionDefault
confirmNo
status_idYes

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations, the description carries the full behavioral burden and does well: it labels the operation a WRITE ACTION, states the confirmation gate, and ties it to the confirm parameter. It omits irreversibility, behavior when the status does not exist or is not owned, and rate limits, which keeps it short of a 5.

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

Conciseness5/5

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

Two sentences, no filler, with the action and the safety gate front-loaded before the parameter requirement. Every clause earns its place.

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 destructive two-parameter tool with no annotations and no output schema, the definition covers the essentials an agent needs to act safely: what is deleted, the ownership constraint, and the confirmation gate. Failure modes and reversibility are the only notable omissions.

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

Parameters3/5

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 explains the semantics of confirm ('Requires confirm=true') but says nothing about status_id format or where it comes from, leaving half the parameters undocumented.

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?

Specific verb (Delete) plus resource (status) with a clear ownership scope ('one of the user's own statuses'), which separates it from get_status, post_status and favorite in the sibling list. An agent can identify the operation without opening the 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?

Gives an explicit precondition for invocation: call only after the user has explicitly confirmed this exact action and content in chat. It does not name alternative tools or describe what to do when confirmation is absent, but the gating condition is unambiguous.

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

favoriteA

Favorite (action='create') or unfavorite (action='destroy') a status. WRITE ACTION: only call after the user has explicitly confirmed this exact action and content in chat. Requires confirm=true.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionNocreate
confirmNo
status_idYes

TDQS

A4.4/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does disclose the key trait: this is a WRITE ACTION requiring explicit user confirmation and confirm=true, which is exactly the safety context an agent needs. It omits auth requirements, rate limits, and what happens if confirm is omitted/false (default false is only visible in the schema).

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

Conciseness5/5

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

Two tight sentences with the core capability first and the safety gate second. No filler, and the critical constraint is capitalized and front-loaded rather than buried.

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 3-parameter write tool with no annotations and no output schema, the description covers the essential behavioral contract (write + confirmation). It would be fully complete with a note on return behavior or failure when confirm is absent, but nothing needed to invoke it correctly is missing.

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%, so the description must compensate, and it does: it explains the two meaningful values of 'action' ('create' vs 'destroy') and the required 'confirm=true' semantics, which the bare schema does not. 'status_id' is left unexplained but is self-evident from the purpose.

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+resource pair ('favorite/unfavorite a status') and clarifies that a single tool handles both directions via the action parameter. This distinguishes it from the sibling 'favorites' (a listing tool) and 'post_status'/'delete_status' 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?

Gives a clear gating condition: only call after the user has explicitly confirmed this exact action and content in chat, plus the confirm=true requirement. It does not name alternative siblings (e.g., 'favorites' for reading), but the when-to-use context is explicit and actionable.

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

favoritesC

Read a user's favorited statuses (empty = the authenticated user).

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo
countNo
user_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

C2.9/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full behavioral burden. 'Read' implies a non-mutating call, but pagination behavior (page/count interaction), result limits, ordering, and auth requirements are all unstated for a tool with three parameters.

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?

A single short sentence, front-loaded with the resource and action, with the scoping rule appended. No wasted words, though the brevity is partly under-specification rather than pure economy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described, but with 0% schema coverage the description should compensate for the undocumented page/count parameters and lack of any read-only or auth statement. As written, an agent must guess at pagination semantics.

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

Parameters2/5

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

Schema description coverage is 0%, and the description only clarifies one of three parameters (user_id defaults to the authenticated user). The meaning of 'page' and 'count' — units, defaults, interaction — is left entirely undocumented in both schema and description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Read ... favorited statuses'), which is clear on its own. It implicitly distinguishes from the sibling 'favorite' (the write action) but never says so explicitly, leaving a possible ambiguity between reading favorites and favoriting a status.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The parenthetical 'empty = the authenticated user' gives a useful rule for when to omit user_id, but there is no guidance on when to use this versus home_timeline, user_timeline, or mentions. Usage is only implied by the resource name.

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

friendshipA

Follow (action='create') or unfollow (action='destroy') a user. WRITE ACTION: only call after the user has explicitly confirmed this exact action and content in chat. Requires confirm=true.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionNocreate
confirmNo
user_idYes

TDQS

A4.4/5.0
Behavior4/5

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

With no annotations provided, the description carries the full behavioral burden and does disclose the most important trait: this is a write action gated behind explicit confirmation and a confirm=true flag. It stops short of describing side effects on timelines, rate limits, or failure behavior.

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

Conciseness5/5

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

Two sentences, zero waste, with the operation mapping and the safety guardrail both front-loaded. Every sentence earns its place.

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 mutation tool with no annotations and no output schema, the description supplies the critical confirmation protocol. Remaining gaps are minor: whether unfollow also requires confirmation, and what a failed or rejected call returns.

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 description coverage is 0%, so the description must compensate — and it does for the two non-obvious parameters: action ('create'=follow, 'destroy'=unfollow) and confirm (must be true for the write). user_id is self-evident from the name, leaving only minor gaps.

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?

The description names the two specific operations (follow/unfollow) and maps them to the action values, fully disambiguating the opaque name 'friendship'. An agent can distinguish this from siblings like favorite or post_status without opening the 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?

It states a clear precondition for use: only call after the user has explicitly confirmed the exact action and content in chat. It doesn't name alternative tools or when-not-to-use cases, but no sibling overlaps with follow/unfollow semantics.

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

get_contextC

Get the conversation context (reply chain) of a status.

ParametersJSON Schema
NameRequiredDescriptionDefault
status_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

C2.8/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full behavioral burden. 'Get' implies a read-only operation, but nothing is said about ordering, reply depth, pagination, or authentication requirements for the reply chain.

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?

A single compact sentence with no filler, and the scoping detail '(reply chain)' is front-loaded. It is arguably under-specified rather than verbose, but it wastes no words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value shape need not be explained, and the tool has only one parameter. However, with no annotations the description should say more about the reply-chain semantics (depth, ordering, pagination) to be fully callable.

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

Parameters2/5

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

Schema description coverage is 0% for the single required parameter status_id. The description only indirectly implies that the parameter identifies 'a status' and adds no format or source detail to compensate for the empty schema description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb (Get) and resource (the conversation context / reply chain of a status), and the parenthetical '(reply chain)' disambiguates it from the sibling get_status, which retrieves the status itself. It is clear without opening the schema, though it never names the sibling it differs from.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance and no mention of alternatives such as get_status or the various timeline tools. The agent must infer that this is for expanding a thread rather than fetching a single status.

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

get_statusC

Get one status by id.

ParametersJSON Schema
NameRequiredDescriptionDefault
status_idYes

TDQS

C2.7/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden. It reveals nothing about return shape, visibility/permission constraints (e.g., whether a private status returns an error), or error behavior for an unknown id. For a zero-annotation tool this is a notable gap.

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?

A single front-loaded sentence with zero waste. It is concise to the point of under-specification, but nothing is redundant or buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With one required parameter, no output schema, and no annotations, the description should have compensated for all three. Instead it supplies only a bare purpose statement, leaving an agent without enough context to know what a successful or failed call yields.

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

Parameters2/5

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

One parameter at 0% schema description coverage. 'by id' loosely signals that status_id is an identifier, but nothing is said about its format (numeric vs. string id), where to source it, or whether it is required — the schema marks it required but the description does not reinforce this.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with a scoping qualifier: 'Get one status by id.' The phrase 'one status' implicitly contrasts with the timeline siblings that return many statuses, but it does nothing to distinguish itself from get_user, get_context, or post_status.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this versus home_timeline, mentions, or get_context, and no prerequisites stated. The agent must infer that it needs a status_id it obtained elsewhere.

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

get_userA

Get a user's profile by id (empty = the authenticated user).

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idNo

TDQS

A3.5/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full behavioral burden. It discloses the empty-string default behavior, but says nothing about authentication requirements, whether the profile is public/private, or what happens on an unknown id, leaving the read-only safety profile only implied by the verb 'Get'.

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

Conciseness5/5

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

A single tight sentence with the key behavioral detail (empty = self) front-loaded in parentheses. No wasted words.

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 simple one-parameter read tool with no output schema or annotations, the description covers the essential selection key and the default case. Adding auth or error-behavior context would make it fully complete, but the gap is minor at this complexity.

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% and the lone parameter has only a bare default of "", so the schema alone is uninformative. The description compensates by defining the id semantics and the special empty-value case, fully covering the single parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Get a user's profile') and clarifies the retrieval key (by id). The parenthetical 'empty = the authenticated user' further sharpens scope, though it does not explicitly distinguish this lookup from timeline/status siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies usage by explaining the empty-id case, which tells the agent how to fetch the caller's own profile. However, it gives no when-to-use/when-not guidance relative to siblings like user_timeline or verify_credentials.

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

home_timelineC

Read the authenticated user's home timeline (statuses from people they follow). count 1-60.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo
countNo
max_idNo
since_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

C2.9/5.0
Behavior3/5

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

With no annotations, the description carries the full behavioral burden. It discloses that this is a read operation and adds the 'count 1-60' constraint beyond the schema, but it omits authentication requirements, pagination behavior, and rate limits.

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?

The description is very tight and front-loaded, using two short sentences with no wasted words. The fragment 'count 1-60' is slightly abrupt but informative.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter read tool with an output schema and no annotations, the description is missing pagination semantics for max_id/since_id/page and any usage guidance. It covers the core purpose and count limit but is not complete enough to call the tool confidently without opening the schema.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate for four undocumented parameters. It adds a useful count range, but says nothing about page, max_id, or since_id, leaving most parameter semantics unexplained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Read the authenticated user's home timeline,' and parenthetically clarifies content as 'statuses from people they follow.' This distinguishes it from public timelines and mentions implicitly, but it does not explicitly name or differentiate from any sibling tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus alternatives like user_timeline, mentions, or public_timeline. The implied usage is clear from the purpose statement, but no exclusion or alternative routing is provided.

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

mentionsB

Read statuses that mention the authenticated user. count 1-60.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo
countNo
max_idNo
since_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It does disclose that results are scoped to mentions of the authenticated user and states the valid count range (1-60), which is genuine behavioral context, but it says nothing about pagination behavior, auth requirements, or result ordering.

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?

Two short sentences, front-loaded with the core purpose and followed by the one constraint worth surfacing. No filler, though it is arguably under-specified rather than optimally concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained. For a simple read tool this is nearly adequate, but the total absence of parameter documentation and any usage/routing guidance leaves real gaps for an agent picking among many sibling feeds.

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

Parameters2/5

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

Schema description coverage is 0% across 4 parameters (page, count, max_id, since_id). The description only documents the count range and leaves page, max_id, and since_id entirely unexplained, so the documentation gap is largely uncompensated.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Read statuses') and scopes it to those mentioning the authenticated user, which distinguishes it from the timeline siblings (home_timeline, user_timeline, public_timeline). It never names a sibling explicitly, but the 'mention the authenticated user' qualifier is enough to route correctly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance and no mention of alternatives. Given the crowded set of timeline/search siblings, an agent has to infer that this is the mentions-only feed rather than home_timeline or search_public_timeline.

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

post_statusA

Post a new status (发饭). Optional in_reply_to_status_id / repost_status_id. WRITE ACTION: only call after the user has explicitly confirmed this exact action and content in chat. Requires confirm=true.

ParametersJSON Schema
NameRequiredDescriptionDefault
statusYes
confirmNo
repost_status_idNo
in_reply_to_status_idNo

TDQS

A3.7/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does disclose the key behavioral traits: this is a WRITE ACTION, it requires explicit user confirmation, and it needs confirm=true. It omits irreversibility, rate limits, and what the call returns, so not a 5.

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

Conciseness5/5

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

Front-loaded with the action, then the optional threading params, then the safety constraint. Every clause carries information and nothing is padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

A write tool with no annotations, no output schema, and 0% parameter coverage needs more than this. The safety/confirmation guidance is solid, but the threading and repost parameters remain opaque and no return behavior is indicated.

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

Parameters2/5

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

Schema description coverage is 0% across 4 parameters, so the description must compensate. It names in_reply_to_status_id and repost_status_id and flags confirm, but supplies no meaning, format, or valid-value guidance, and never explains the required 'status' parameter beyond the verb.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Post a new status'), which clearly distinguishes it from read siblings like get_status and destructive siblings like delete_status. It stops short of naming any sibling explicitly, but the purpose is unambiguous.

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?

Gives an explicit when-to-call condition: only after the user has explicitly confirmed the exact action and content in chat, plus the confirm=true requirement. It does not name when-not to use it or route to alternative write tools (favorite, friendship), so it falls short of the top band.

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

public_timelineC

Read the latest public statuses on Fanfou. count 1-60.

ParametersJSON Schema
NameRequiredDescriptionDefault
countNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

C2.9/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full behavioral burden. 'Read' implies a safe read operation, but it says nothing about authentication requirements (Fanfou timelines typically need a session), rate limits, or ordering/refresh semantics, leaving real gaps for a network-backed tool.

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?

Two short, front-loaded fragments with no filler; the purpose leads and the constraint follows. The second fragment ('count 1-60') is telegraphic, but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and the one parameter is at least bounded. Still missing are auth requirements and how this feed differs from the sibling timelines, which an agent needs to select it correctly.

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

Parameters3/5

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

Schema coverage is 0%, so the description must compensate for the single 'count' parameter. It usefully supplies the valid range (1-60) that the schema omits, but does not mention the default of 20 or what happens on out-of-range input, so the compensation is partial.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: 'Read the latest public statuses on Fanfou,' which tells an agent exactly what data comes back. However, it offers no differentiation from close siblings like home_timeline, user_timeline, or search_public_timeline, so the agent must infer that 'public' means unauthenticated/global feed.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no contrast against the five sibling timeline tools, and no prerequisites or auth context. The only supplemental text ('count 1-60') is a parameter constraint, not usage guidance.

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

search_public_timelineC

Search public statuses by keyword (supports 'a b' AND and 'a|b' OR).

ParametersJSON Schema
NameRequiredDescriptionDefault
qYes
countNo
max_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

C2.7/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full behavioral burden, yet it only discloses query operator syntax. It says nothing about auth requirements, rate limits, pagination behavior, or that this is a read-only lookup, which matters for a tool with a max_id cursor.

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?

A single tight sentence with the resource up front and the syntax detail in parentheses. Nothing is wasted, though there is little content overall.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be described, but with no annotations and 0% parameter coverage the definition should still cover pagination (max_id), result limits, and access constraints. Those omissions leave an agent unable to page or scope results reliably.

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

Parameters2/5

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

Schema description coverage is 0% and there are three parameters. The description usefully explains the 'a b' AND / 'a|b' OR syntax for q, but count and max_id are left entirely undocumented in both schema and description, so pagination semantics are lost.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb and resource ('Search public statuses by keyword') and the 'public' qualifier implicitly separates it from search_user_timeline and public_timeline. It stops short of explicitly naming which sibling to prefer, so it's clear but not fully differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit when-to-use guidance, no mention of alternatives (e.g. search_user_timeline for a single account), and no stated prerequisites. Usage is only inferable from the word 'public' in the resource.

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

search_user_timelineB

Search within one user's statuses (user_id empty = the authenticated user).

ParametersJSON Schema
NameRequiredDescriptionDefault
qYes
countNo
max_idNo
user_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure and delivers very little. It does not state authentication requirements, rate limits, pagination behavior (relevant given a max_id param), or result ordering. Only the user_id default behavior is disclosed.

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?

A single tight sentence with the scoping condition front-loaded and no filler. It is efficient but leans on the reader to infer the rest, which is under-specification rather than a structural flaw.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, which lightens the burden. Still, four undocumented parameters, no annotations, and no mention of auth or pagination leave meaningful gaps for a search tool with a required query parameter.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate and largely does not. It explains only user_id's default semantics; q, count, and max_id are left with bare titles, and the pagination meaning of max_id (return results before this ID) is never conveyed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb (search) and a bounded resource (one user's statuses), and the parenthetical scope makes it clear this is a per-user timeline search rather than a global one. It does not explicitly name competing siblings like user_timeline or search_public_timeline, so differentiation is only implied by scope wording.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The parenthetical 'user_id empty = the authenticated user' gives a concrete default behavior an agent can act on. However, it never states when to prefer this over user_timeline (unfiltered list) or search_public_timeline (global search), so selection guidance is only inferable.

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

user_timelineB

Read a user's statuses. user_id empty = the authenticated user. count 1-60.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo
countNo
max_idNo
user_idNo
since_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.1/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It does disclose the read-only nature ('Read') and the count range constraint ('count 1-60'), but omits pagination behavior and auth requirements. Useful but incomplete for a no-annotation tool.

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?

Three short, front-loaded clauses with no filler; the core purpose leads and constraints follow. Efficient, though its extreme terseness is what leaves the pagination parameters unexplained.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With five parameters at 0% schema coverage and no annotations, the description is too sparse: the ID-based pagination fields (max_id, since_id, page) are essential to calling this correctly and are never described. An output schema exists, so return values need not be covered, but the input side remains under-specified.

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

Parameters2/5

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

Schema coverage is 0%, so the description must compensate for all five parameters. It clarifies user_id (empty = authenticated user) and count (1-60), but leaves page, max_id, and since_id entirely undocumented, and these cursor parameters are non-obvious without explanation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Read a user's statuses'), which clearly maps to a timeline-fetch tool. It does not explicitly differentiate from close siblings like home_timeline or search_user_timeline, but the user_id default hint gives enough to separate it from the authenticated-user variants.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'user_id empty = the authenticated user' implies when to use it for self vs. another user, which is genuine contextual guidance. However, there is no explicit when-to-use/when-not guidance relative to siblings such as home_timeline or mentions.

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

verify_credentialsA

Return the authenticated Fanfou account (read-only).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior3/5

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

With no annotations, the description carries full burden, and it does disclose the read-only, no-side-effect nature plus what is returned. However it omits auth-failure behavior (e.g. what happens with an invalid token) and any note that this doubles as a credential check, which is the key trait of a verify endpoint.

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

Conciseness5/5

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

A single short sentence, front-loaded with the return value and its scope qualifier. No filler, nothing repeated from structured fields.

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 zero-parameter read-only call with no output schema, the description gives what an agent needs: the returned entity and its authenticated scope. It is slightly thin on return shape and error behavior, but those are minor for a tool this simple.

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?

The tool takes zero parameters, so the baseline of 4 applies; there is nothing for the description to disambiguate beyond what the empty schema already conveys.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Return the authenticated Fanfou account') with the scope qualifier 'authenticated', which distinguishes it from sibling get_user. It doesn't explicitly name that sibling, so it falls short of the top mark.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the word 'authenticated' hints this is the identity/auth-check call rather than an arbitrary profile lookup. There is no explicit when-to-use or when-not-to-use statement and no reference to get_user as the alternative.

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.

  1. 15 tool updatesv0.1.0
    • First observeddelete_status
    • First observedfavorite
    • First observedfavorites
    • First observedfriendship
    • First observedget_context
    • First observedget_status
    • First observedget_user
    • First observedhome_timeline
    • First observedmentions
    • First observedpost_status
    • First observedpublic_timeline
    • First observedsearch_public_timeline
    • First observedsearch_user_timeline
    • First observeduser_timeline
    • First observedverify_credentials

TDQS

B3.3/5.0

Scored across 15 tools

Disambiguation4/5

Most tools have clearly distinct resource+scope (home_timeline vs user_timeline vs public_timeline vs mentions are separated by audience, not confused). The one real overlap is verify_credentials versus get_user with an empty id, which both return the authenticated user, and the two search_* variants could be momentarily confused. Otherwise boundaries are clean.

Naming Consistency3/5

The set mixes verb_noun (get_user, get_status, post_status, delete_status) with bare-noun reads (home_timeline, user_timeline, mentions, favorites) and bare-noun writes (favorite, friendship). The convention is readable and mostly predictable, but the inconsistent use of get_/search_ prefixes across reads keeps it from being fully uniform.

Tool Count4/5

15 tools is at the upper edge of the well-scoped band but each one maps to a distinct Fanfou operation (timelines, search, status lifecycle, favorites, follow, context). Nothing feels redundant enough to cut. Slightly heavy but justified by the surface.

Completeness4/5

Core lifecycle is covered: read/search timelines, get status and reply context, post/delete, favorite/unfavorite, follow/unfollow. Gaps exist (no follower/following lists, no direct messages, no user search), but these are minor for the primary microblogging workflows an agent would run.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    MCP server for interacting with the X platform (Twitter) via MCP clients like Claude, Cursor AI, and Windsurf AI.
    20
    1 npm
    6
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    MCP server to read X (Twitter) posts, threads, replies, quotes, and search using your own logged-in session, no API key required.
    8
    3
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Twitter/X MCP server for the API v2, enabling users to manage profiles, posts, likes, retweets, and follows through natural language using a stateless Streamable HTTP transport with OAuth user access token authentication.
    9 npm
    ISC
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables MCP-based interaction with the X (Twitter) API v2, supporting reads like timeline, mentions, and search, and writes through a two-step draft-and-confirm process that ensures human-visible previews before any public post.
    -