Playwright-mcp has 10 tools with basic schemas and minimal descriptions. All tools have input schemas with type definitions, but descriptions are extremely terse (8-40 chars, well below the 50-200 char baseline for LLM-optimized tools). Parameter descriptions are entirely absent, LLMs cannot infer what 'page_id' means or when to use it. No output schemas documented. Error handling is minimal (ValueError exceptions with generic messages). The server uses global mutable state (pages dict, current_page_id) which violates stateless request handling. No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear read/write distinctions. Resource support exists but is underutilized.
Click on an element by selector
Get the current page HTML content
List all available browser pages
Get text content from an element
Navigate to a URL
Create a new browser page
Switch to a different browser page
Take a screenshot of the current page
All tool descriptions are under 20 characters (e.g., 'Navigate to a URL', 'Click on an element by selector'). LLMs cannot determine when to use navigate vs click vs type without richer context. Descriptions must explain WHAT, WHEN, and any prerequisites.
No parameter descriptions anywhere. 'page_id' appears in 8 tools but is never explained, is it required? What format? When should it be omitted? 'selector' is used in 5 tools without guidance on CSS vs XPath.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | F | 42 | 2026-07-28+ | v2 |
Type text into an input element
Wait for an element to be visible on the page
No output schemas documented. Tools return TextContent or ImageContent but LLMs don't know what fields to expect. E.g., does navigate() return just a success message, or does it include the final URL? Does get_page_content() return raw HTML or structured DOM?
No tool annotations despite clear read/write distinctions. navigate, click, type, new_page, switch_page are destructive/write operations but lack destructiveHint=true. get_text, get_page_content, take_screenshot, get_pages, wait_for_selector are read-only but lack readOnlyHint=true. Annotations help LLMs reason about side effects and retry safety.
Global mutable state (pages dict, current_page_id, browser, context) violates stateless request handling. Each request should be self-contained. If the server crashes and restarts, all page references are lost. Per 2026-07-28 spec, protocol is stateless, state must be managed by the client or persisted externally.