Static source inference · medium confidence · detected: Logging
Deprecated protocol patterns detected
Summary
This server demonstrates solid tool definition quality with consistent patterns across 26 tools. All tools have explicit names starting with action verbs (list_, get_, create_, update_, delete_, set_, purge_), clear descriptions, and typed parameters with descriptions. However, output schemas are not documented in the visible source code, parameter descriptions lack specific constraints (enums, ranges, formats), and error handling is absent from the tool signatures. The codebase shows good hygiene (ruff linting, strict mypy, comprehensive tests) but the MCP tool definitions themselves lack the depth needed for A-grade quality. Parameter descriptions are present but generic (e.g., 'Zone ID (32-character hex string)' is informative but does not explain WHY to pass it or WHEN it's needed). No tool annotations (readOnlyHint, destructiveHint, idempotentHint) are visible, despite clear risk classification in the metadata. The server mirrors the Cloudflare API signature closely, which is reasonable for domain coverage but sometimes at the cost of agent ergonomics (e.g., accepting zone_id OR zone_name in get_zone_tool requires conditional logic that could be wrapped in the tool).
Output schemas not documented. The tool definitions provide input schemas but do not describe what fields are returned or what structure the agent should expect. This forces LLMs to reason blindly about response structure, increasing hallucination risk and preventing proper chaining of tools.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). Risk metadata exists in the evaluation brief (READ_ONLY, WRITE, DESTRUCTIVE) but is not encoded in the FastMCP tool definitions. This prevents clients from rendering appropriate warnings or enforcing access controls.
delete_dns_record_tool
Recommendations
Document the output schema for every tool. Use the FastMCP response_model parameter or add a Returns section to each docstring describing the exact fields returned (e.g., 'Returns dict with keys: id (str), name (str), type (str), created_on (str ISO 8601), modified_on (str ISO 8601), status (str), ...)'. This enables agents to plan downstream tool calls and extract the right data.
Add tool annotations to FastMCP tool definitions. Use @mcp.tool() decorators with readOnlyHint=True for list_* and get_* tools, destructiveHint=True for delete_* tools, and idempotentHint=True for tools that can be safely retried. Example: @mcp.tool(readOnlyHint=True) async def list_zones_tool(...). This signals to clients that these tools are safe read operations.
Convert informal constraints to formal schema constraints. For list_zones_tool status parameter, add enum=['active', 'pending', 'initializing', 'moved', 'deleted'] to the schema. For per_page parameters, add minimum=1, maximum=50 (or 100 for DNS records). For page, add minimum=1. For ttl, add minimum=1. This prevents invalid input from LLMs and self-documents the API.
Document array item schemas for rules parameters. For set_request_header_rules_tool, create a sub-schema explaining that 'rules' is an array of objects with required properties like 'action', 'header', and 'value'. Example docstring addition: 'rules: Array of rule objects. Each rule is {"action": "set|remove", "header": string (case-insensitive), "value": string (if action=set)}'. Provide 2-3 realistic examples in inline comments or a separate example section.
Spec posture evidence
Inferred effective spec: <=2025-11-25.
Relies on Logging (deprecated) - log to stderr or use OpenTelemetry
Score history
Overall score trend
↑ 0 points across a rubric change (v1 → v2)
61/100
Scored
Grade
Overall
Spec posture
Rubric
2026-09-22
C
61
<=2025-11-25
v2
2026-03-09
C
61
-
v1
get_security_events_tool
read onlyauthsource verified80/100
Get security/firewall events grouped by action and source.
Parameter descriptions lack constraints and examples. Enum values, ranges, formats, and patterns are referenced in parameter names and descriptions but not formalized in the schema. E.g., 'status' param in list_zones_tool says 'Filter by status (active, pending, initializing, moved, deleted)' in the description but no enum constraint is defined, allowing LLMs to pass invalid statuses.
Array parameters lack itemized schema. set_request_header_rules_tool, set_response_header_rules_tool, set_url_rewrite_rules_tool, create_page_rule_tool, update_page_rule_tool, and purge_cache_tool all accept array parameters (rules, targets, actions, files, tags, hosts, prefixes) but do not document the structure of array items (e.g., object properties, required fields, enum values). This leaves agents guessing at the structure of nested objects.
No error handling guidance. Tool signatures do not document failure modes, error conditions, or recovery strategies. For example, delete_dns_record_tool provides no guidance on what happens if the record is not found, if the zone is not found, or if the API token lacks permission. Agents cannot distinguish retryable errors from permanent failures.
get_zone_tool accepts two mutually exclusive parameters (zone_id and zone_name) but does not document the precedence or what happens if both are provided. The description says 'Provide either zone_id or zone_name, not both' but this is not enforced in the schema and will not be understood by all MCP clients.
Pagination parameters lack clear defaults and bounds. Tools like list_dns_records_tool mention 'max 100 (default: 100)' in descriptions but do not enforce min/max in the schema. LLMs could pass per_page=0, per_page=999, or page=-1, causing API errors. Formal schema constraints (minimum, maximum) are missing.
Optional parameters not clearly marked. Many parameters like 'type', 'name', 'content' in list_dns_records_tool are optional but the description does not state 'optional' or provide guidance on what happens if omitted. Descriptions should explicitly say 'optional, if omitted, no filtering is applied by this field.'
No pagination guidance for list tools. Descriptions do not explain whether pagination is required to fetch all results, whether there is a hard limit, or what cursor/next-page mechanism is used (offset-based vs cursor-based). This is critical for agents planning multi-step discovery workflows.
Description for 'targets' and 'actions' in page rule tools is too vague. 'URL pattern targets' and 'Page rule actions' do not explain what values are valid, whether they are strings, objects, or arrays of objects, or what properties each element must have. Agents cannot construct valid page rules without trial and error or external API documentation.
create_page_rule_toolupdate_page_rule_tool
Add error guidance to tool descriptions. For delete_dns_record_tool, extend the docstring with an 'Raises' section: 'Raises: UserError if record_id not found in zone; UserError if zone_id not found; UserError if API token lacks write permission.' This tells agents what errors are expected and which are retryable vs permanent.
Clarify mutually exclusive parameters. For get_zone_tool, add a note in the description: 'Either zone_id or zone_name must be provided, not both. If both are provided, zone_id takes precedence.' Better yet, split into two tools (get_zone_by_id and get_zone_by_name) to eliminate ambiguity, or add validation logic that rejects both being set and returns a clear error message.
Expand descriptions of complex parameters. For create_page_rule_tool 'targets' and 'actions', add inline examples: 'targets: Array of URL patterns (strings). Examples: ["example.com/api/*", "example.com/admin/*"]. supports wildcards (*) for path matching.' And 'actions: Array of action objects. Each action is {"id": string, "value": string}. Common actions: forward_url, cache_on_cookie, email_obfuscation. Consult Cloudflare API docs for full list.'
Add pagination disclaimers. For list_zones_tool, add: 'Note: Results are paginated. If more than 50 zones exist, call multiple times with increasing page numbers to fetch all. Total zone count is returned in the response metadata.' This guides agents to loop or request all pages if needed.
Mark optional parameters explicitly. In docstrings, prefix optional params with '[Optional]'. Example: 'type: [Optional] Filter by record type (A, AAAA, CNAME, ...). If omitted, all record types are returned.' This is clearer than relying on the schema alone.
Add permission notes to write/destructive tools. For delete_dns_record_tool, add: 'Requires: write:dns_records permission on the zone. If the API token lacks this scope, the call will fail with a 403 Forbidden error.' This helps agents understand prerequisites and surface permission errors to users.
Document response cardinality. For get_top_pages_tool and get_traffic_by_country_tool, clarify: 'Returns array of up to limit results (default 15 for pages, 20 for countries). If fewer results are available, the returned array is shorter.' This prevents agents from assuming exactly limit results are always returned.
Add idempotency notes. For create_dns_record_tool, clarify: 'Creating a DNS record with identical name, type, and content twice will result in two separate records (not idempotent). Use update_dns_record_tool if you need to modify an existing record.' This prevents agents from retrying on transient failures and creating duplicates.