Static source inference · medium confidence · detected: stateful session
Deprecated protocol patterns detected
Summary
The xhs-mcp server has 26 tools across 9 modules (account, auth, content, publish, interaction, stats, download, draft, creator, notification, explore). Tool naming follows verb_noun conventions well (add_account, search_notes, publish_note, etc.). Descriptions are generally present but often brief (10-50 chars) and lack LLM-optimized guidance on WHEN to use tools, prerequisites, or recovery paths. Input schemas are visible for all tools and include field types and basic descriptions. However, parameter descriptions are minimal (e.g., 'Account ID' without explaining format or valid values), and output schemas are not documented in the source. Critical gaps: no enum constraints where applicable (e.g., notification 'type' has enum but others like 'filters' in search_notes are unconstrained objects), no pagination guidance despite list tools returning potentially large result sets, no documented output schemas, and no explicit error recovery guidance. Tool composition is reasonable (single responsibility for most tools), but some like 'explore' combine interaction simulation with session management, and the interaction tools (like_note, post_comment, reply_comment) lack dry-run or confirmation patterns for irreversible operations.
Missing output schemas: No documented return types for any of the 26 tools. LLMs cannot infer what fields to expect in responses, forcing them to guess or make assumptions about downstream data flow.
Minimal parameter descriptions: Many parameters documented with 10-30 character descriptions (e.g., 'Account ID', 'Note ID', 'Comment content'). LLMs need format guidance (e.g., 'Account ID (alphanumeric, 8-32 chars)'), range constraints, and dependencies between parameters.
Recommendations
Document output schemas for all 26 tools. Specify field names, types (string, number, array, object), and whether fields are always present or conditional. Example for get_notes: {notes: [{noteId: string, title: string, author: string, likeCount: number, commentCount: number}], total: number, cursor?: string}
Expand parameter descriptions from 10-30 chars to 50-150 chars. For each parameter, add: (1) what it controls, (2) valid format/range/values, (3) dependencies on other parameters. Example: 'accountId: The Xiaohongshu account ID to use (alphanumeric, 8-32 chars; must exist in account pool; required for all authenticated operations).'
Convert unconstrained 'filters' and 'state' objects to explicit parameters with type definitions or enums. For search_notes, replace generic 'filters' with specific params like: filter_author_id?, filter_min_likes?, filter_date_range? (with ISO 8601 format). For add_account 'state', document the expected Playwright storage state schema (cookies array with name/value/domain, localStorage object).
Add pagination to list_accounts, list_drafts, get_my_published_notes, get_notifications, search_notes. Introduce: limit (1-100, default 20), offset (default 0), and return {total: number, items: [...], hasMore: boolean, cursor?: string}. Document that default limit=20 is the baseline; agents can request more up to 100 to balance latency vs context size.
Document error conditions and recovery paths for each tool. For publish_note: 'May fail if account not logged in (retry login), content violates Xiaohongshu policy (ask user to revise), or network timeout (retry after 5s). Always returns status code and error message detailing which part failed.'
Spec posture evidence
Inferred effective spec: 2026-07-28+.
Relies on Stateful initialize / Mcp-Session-Id (removed; protocol is stateless) - make each request self-contained
Unconstrained object parameters: 'filters' in search_notes and 'state' in add_account are documented as generic objects with no schema details. LLMs cannot determine what keys/values are valid, leading to malformed payloads.
Missing pagination guidance: list_accounts, list_drafts, get_my_published_notes, and get_notifications lack explicit pagination parameters (limit, offset, page_size) and do not document max result counts.
No error recovery guidance: No documented error conditions, recovery steps, or classification (retryable vs user-fixable vs fatal). Tools like publish_note and post_comment are irreversible but have no guidance on what can go wrong or how to handle failures.
Irreversible operations lack confirmation/dry-run: publish_note, post_comment, reply_comment, and delete_draft modify state irreversibly. No dry-run, preview, or confirmation_required pattern documented to prevent agent mistakes.
Tool descriptions too brief: 14 of 26 tools have descriptions under 50 characters (below p10 of 34, within range, but below LLM-optimized baseline of 50-200). Descriptions like 'Check if account is logged in' and 'Like or unlike a note' lack WHEN to use and prerequisites.
explore tool combines multiple concerns: Simulates user behavior (opening, liking, commenting) AND manages sessions. Should split into separate tools: simulate_engagement and manage_session for clearer composition and independent reusability.
No audit/permission documentation: No tool mentions required permissions (e.g., 'write:account', 'publish:content'). Agents deploying this server cannot enforce least-privilege configs or track what scope each tool requires.
Add dry_run parameter to publish_note, post_comment, reply_comment, delete_draft. When dry_run=true, simulate the operation and return what would happen without committing. Enables agents to preview before executing irreversible actions.
Declare required permissions for each tool in the description or via a new 'permissions' field. Example: publish_note requires 'publish:content', post_comment requires 'interact:content'. This enables least-privilege agent configuration.
For tools returning large lists (search_notes, get_my_published_notes, get_operation_log), add explicit result-capping in the description: 'Returns up to 50 results per request. Use pagination to fetch more. Total results capped at 10,000 to prevent context exhaustion.'
Clarify dependencies between tools in descriptions. Example in search_notes: 'To filter by specific user, call get_user_profile first to obtain userId if you only have a username.'
Split explore into two tools: (1) simulate_engagement (given accountId, interests, durations, start/stop logic handled outside), (2) manage_explore_sessions (list, stop, get status). This separates concerns and enables agents to compose them independently.