Static source inference · medium confidence · detected: Logging
Deprecated protocol patterns detected
Summary
NGCBot-MCP-Server exhibits significant quality gaps across naming, descriptions, parameter validation, and error handling. While 5 tools are defined with basic schemas, the implementations lack clarity for LLM reasoning and fail to follow Agentic Tool Patterns. Tool names are acceptable but descriptions are minimal (many under 50 chars). Parameter descriptions exist but lack actionable constraints. Output schemas are not documented. Error handling returns generic success/error dicts without recovery guidance. No tool annotations. The server targets WeChat integration (a specialized domain) but the definitions do not reflect production-grade tool design.
Tool descriptions are too brief (10-40 chars) and lack actionable context. 'Give WeChat friends or group chats send files' (translated) does not explain WHEN to use this tool, what happens on success/failure, or how it differs from send_image/send_text. LLMs cannot reliably select among three send_* tools without more context.
Parameter 'receiver' accepts both wxId (e.g., 'wxid_123') and group chat IDs ('123@chatroom') or names ('Group Name'), but the description does not make this flexibility clear. LLMs may try one format and fail rather than adapting. No guidance on format preference or resolution logic.
Output schemas are not documented in the tool definitions. The code returns {'status': 'success'|'error', 'message': '...'} but LLMs have no visibility into this structure. They cannot reliably extract or chain outputs. Missing documented return types violates the 100% baseline for A+ tools.
Recommendations
Expand tool descriptions to 100 - 150 characters. For send_text, example: 'Send a text message to a WeChat contact (individual) or group. Receiver can be a wxId (wxid_123), group ID (123@chatroom), or contact/group name. Returns success/error status. Send_text is for plain text only; use send_image for images or send_file for attachments.'
Document all parameter formats and constraints explicitly. For 'receiver', specify: 'wxId (e.g. wxid_abc123), group ID (e.g. 123@chatroom), or human-readable contact/group name. If a name is provided, the tool looks it up automatically via get_wxid. Names are case-sensitive.' Do not rely on code comments.
Add explicit output schema documentation to each tool definition. Example for send_text: 'Returns: {status: "success"|"error", message: string}. On success, message contains acknowledgment. On error, message contains reason (invalid receiver, network timeout, etc.).'
Differentiate error responses by type. On invalid wxId, return {status: 'error', errorType: 'invalid_receiver', message: 'Receiver wxid_xyz not found. Valid formats: wxid_XXX, NNN@chatroom, or contact name. Try get_wxid to look up the contact.'}. On network timeout, return {status: 'error', errorType: 'timeout', message: 'NGCBot service timeout. Retryable.'}. LLMs can then decide to retry, ask the user, or try a different receiver.
Add confirmation_before_execute for all send_* and push_room tools. Return {status: 'input_required', action: 'confirm_send_text', details: {recipient: '...' , text: '...', note: 'This will send a real message to WeChat.'}}. Agents then call confirm_send_text(confirm=true) to execute. Prevents accidental mass messages.
Spec posture evidence
Inferred effective spec: <=2025-11-25.
Relies on Logging (deprecated) - log to stderr or use OpenTelemetry
Error responses are generic ('发送失败: <exception>') and do not guide the LLM on recovery. A failed send due to invalid wxId returns the same error as a network timeout. LLMs cannot distinguish retryable errors from user-fixable ones, blocking intelligent error handling.
Irreversible operations (send_file, send_image, send_text, push_room) lack dry-run or confirmation support. An agent mistake sends real messages immediately with no undo option. No confirmation_before_execute pattern.
Tool compositions assume a lookup workflow: if receiver is a name (not wxId), send_text calls get_wxid internally. This is implicit and not documented. An LLM cannot see this dependency in the tool definitions and may call get_wxid unnecessarily or in the wrong order, wasting tokens and context.
Parameter 'msgType' on push_room includes an enum ['black', 'white', 'push'] but lacks descriptions for what each type means. An LLM cannot reason about when to use 'black' vs 'white' vs 'push' without domain knowledge.
Three distinct send_* tools (send_file, send_image, send_text) are named too similarly. LLMs may conflate them or over-reason about which to pick. No clear differentiation in descriptions (e.g., 'use send_image only for .png/.jpg/.gif, not .pdf').
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) are present. Agents cannot infer from the tool definitions alone which operations modify state. send_text, send_file, and send_image are destructive (send real messages) but carry no such marker.
get_wxid does not document pagination or result limits. If there are multiple users/groups with similar names, the tool returns a single match (inferred from code: 'if wxId: return ...'). An LLM cannot see whether the first match is always returned or if there is a search limit, and cannot retrieve alternatives if the first match is wrong.
get_wxid
Rename or alias tools to reduce confusion. Instead of send_file, send_image, send_text, consider send_text_message, send_file_attachment, send_photo_message. Or group them under a single send_message(content_type, receiver, content) tool with contentType enum.
Document the implicit get_wxid lookup in send_* tools. Add to each description: 'If receiver is not a wxId or group ID, the tool calls get_wxid internally to resolve it. This may fail if the name is ambiguous or unknown.'
Enumerate and describe msgType values for push_room. 'msgType must be one of: black (push to group chats in the blocklist), white (push to whitelisted groups), push (push to designated distribution list). Each list is configured server-side.'
Add tool annotations. For fastmcp, register send_text with annotations like @mcp.tool(..., tags=['destructive', 'writes_external'], ...) or equivalent metadata to signal state-modifying operations.
Add result limits and pagination to get_wxid if it can return multiple matches. Document: 'If multiple contacts match the name, returns the first match. To retrieve all matches, use list_contacts() or search_contacts(name).' If list_contacts doesn't exist, clarify the behavior.
Return IDs and names useful for downstream calls. For get_wxid, return {status: 'success', wxId: 'wxid_123', name: 'Jack', type: 'contact'|'group'} so agents can use both the wxId and the verified name in subsequent calls.
Add input validation with actionable errors. In send_text, if receiver is an empty string, return {status: 'error', errorType: 'validation', message: 'Receiver cannot be empty. Provide a wxId (wxid_123), group ID (123@chatroom), or contact name.'}. Current code raises ValueError, which becomes a 500 error to the LLM.
Document dependencies and prerequisites in tool descriptions. Example: 'Before calling send_text to a new contact, verify the contact exists by calling get_wxid with the contact name. This prevents failed sends due to typos.'
Add rate-limit headers or documentation. Specify: 'WeChat messaging has rate limits. Sending >100 messages/minute may trigger temporary blocks. Use push_room in batch mode for bulk sends; avoid loops of send_text calls.' Prevents runaway agent loops from getting the server rate-limited.