web-speed-agent
Allows extraction of article data from TechCrunch pages using the Web Speed API.
web-speed-agent
Local browser automation + Web Speed API integration for authenticated web extraction.
Point an AI agent at any website — including ones that require login — and get back clean, structured data. Credentials stay on your machine. Only extracted HTML goes to the server.
pip install web-speed-agent
playwright install chromiumWant to use this with Claude, Gemini, or other AI clients?
Check out the MCP Server Installation Guide — it's the easiest way to let AI agents log in and extract data through natural language.
We also recommend setting up a master instructional file for your LLM of choice (gemini.md, "Instructions for Claude", etc.). A sample doc can be found here
How it works
Your machine Web Speed server
───────────────────────────────── ──────────────────────────
Playwright browser (local)
↓ navigates, logs in, clicks
↓ gets page HTML
↓ (no passwords sent)
agent.extract(html) ────────→ Advanced extraction engine
←──────── Structured JSONCredentials never leave your machine. The server only sees HTML.
Related MCP server: Agent Identity MCP Server
Quickstart
import asyncio
from web_speed_agent import Agent
async def main():
agent = Agent(api_key="wsp_...") # or set WEBSPEED_API_KEY env var
# Public pages — no browser needed
result = await agent.map("https://techcrunch.com/some-article/")
print(result["article"]["sections"])
# Authenticated pages — browser runs locally
agent.store_credential("mysite", "me@example.com", "mypassword")
async with agent.browser(session_name="mysite") as browser:
page = await browser.new_page()
await page.goto("https://mysite.com/login")
username, password = agent.get_credential("mysite")
await page.fill('[name="email"]', username)
await page.fill('[name="password"]', password)
await page.click('button[type="submit"]')
await page.wait_for_load_state("networkidle")
# Now on a logged-in page — extract it
html = await page.content()
result = await agent.extract(html, page_type="listing")
print(result["listing"]["items"])
asyncio.run(main())Get an API key at getwebspeed.io.
Installation
Requirements: Python 3.10+, a Web Speed API key
pip install web-speed-agent
playwright install chromium
export WEBSPEED_API_KEY="wsp_..."Core concepts
Agent
The main class. Manages credentials, browser sessions, and API calls.
from web_speed_agent import Agent
# API key from argument
agent = Agent(api_key="wsp_...")
# API key from environment variable (recommended)
# export WEBSPEED_API_KEY="wsp_..."
agent = Agent()
# Use as async context manager (auto-closes HTTP client)
async with Agent() as agent:
...Extracting public pages
No browser needed for pages that don't require login:
# Fetch + extract in one call
result = await agent.map("https://example.com/article")
# With JavaScript rendering (for heavy SPAs)
result = await agent.map("https://example.com/spa", js=True)Extracting authenticated pages
Use a local browser session. The browser runs on your machine:
async with agent.browser(session_name="mysite") as browser:
page = await browser.new_page()
await page.goto("https://mysite.com/dashboard")
html = await page.content()
result = await agent.extract(html)The session_name persists cookies to ~/.webspeed/sessions/<name>/ so subsequent runs skip the login step.
Credential management
Credentials are stored in your system keychain (macOS Keychain, Windows Credential Manager, Linux secret-tool). They are never sent to Web Speed servers.
# Store once
agent.store_credential("mysite", "me@example.com", "mypassword")
# Retrieve anywhere
username, password = agent.get_credential("mysite")
# Remove
agent.delete_credential("mysite")Extraction output
The server returns page-type-aware structured data:
# Article
result = await agent.extract(html, page_type="article")
# result["page_type"] → "article"
# result["title"] → "Article Title"
# result["author"] → "Jane Smith"
# result["published_date"] → "2026-05-06"
# result["article"]["sections"] → [{"heading": "...", "paragraphs": [...]}]
# result["article"]["links"] → [{"text": "...", "url": "..."}]
# Product
result = await agent.extract(html, page_type="product")
# result["product"]["name"] → "Wireless Headphones"
# result["product"]["price"] → "$99.99"
# result["product"]["availability"] → "In Stock"
# result["product"]["rating"] → "4.5"
# result["product"]["specs"] → {"Battery": "30h", ...}
# Listing (search results, category pages)
result = await agent.extract(html, page_type="listing")
# result["listing"]["items"] → [{"title": "...", "url": "...", "price": "..."}]
# Auto-detect (default)
result = await agent.extract(html)
# result["page_type"] → "article" | "product" | "listing" | "other"All results include engine: "advanced" — 60–85% more token-efficient than raw HTML.
Examples
Price monitor
import asyncio
from web_speed_agent import Agent
async def check_price(url: str, site_name: str) -> str:
async with Agent() as agent:
agent.store_credential(site_name, "me@example.com", "password", overwrite=True)
async with agent.browser(session_name=site_name) as browser:
page = await browser.new_page()
# Login
await page.goto(f"https://{site_name}.com/login")
user, pwd = agent.get_credential(site_name)
await page.fill('[name="email"]', user)
await page.fill('[name="password"]', pwd)
await page.click('button[type="submit"]')
await page.wait_for_load_state("networkidle")
# Check product
await page.goto(url)
await page.wait_for_load_state("networkidle")
html = await page.content()
result = await agent.extract(html, page_type="product")
return result.get("product", {}).get("price", "unknown")
price = asyncio.run(check_price("https://example.com/product/123", "example"))
print(f"Current price: {price}")Read a private dashboard
import asyncio
from web_speed_agent import Agent
async def get_dashboard_data():
async with Agent() as agent:
async with agent.browser(session_name="analytics") as browser:
page = await browser.new_page()
# Login (first run only — session persists after)
creds = agent.get_credential("analytics")
if not creds:
agent.store_credential("analytics", "me@company.com", "password")
creds = agent.get_credential("analytics")
await page.goto("https://analytics.company.com/login")
await page.fill('[name="email"]', creds[0])
await page.fill('[name="password"]', creds[1])
await page.click('button[type="submit"]')
await page.wait_for_load_state("networkidle")
# Navigate to dashboard
await page.goto("https://analytics.company.com/dashboard")
await page.wait_for_selector(".metrics-table", timeout=10000)
html = await page.content()
result = await agent.extract(html)
return result
asyncio.run(get_dashboard_data())Multi-page scrape while logged in
import asyncio
from web_speed_agent import Agent
async def scrape_inbox():
async with Agent() as agent:
async with agent.browser(session_name="webmail") as browser:
page = await browser.new_page()
# Login
await page.goto("https://mail.example.com/login")
user, pwd = agent.get_credential("webmail")
await page.fill('[name="username"]', user)
await page.fill('[name="password"]', pwd)
await page.click('[type="submit"]')
await page.wait_for_load_state("networkidle")
# Scrape multiple pages
emails = []
for page_num in range(1, 4):
await page.goto(f"https://mail.example.com/inbox?page={page_num}")
await page.wait_for_load_state("networkidle")
html = await page.content()
result = await agent.extract(html, page_type="listing")
emails.extend(result.get("listing", {}).get("items", []))
return emails
asyncio.run(scrape_inbox())AI agent integration (MCP)
The included MCP server lets Claude Desktop, Gemini CLI, and any MCP-compatible agent use the SDK directly. The agent can log in, navigate, click, and extract — all through natural language.
Start the MCP server:
WEBSPEED_API_KEY="wsp_..." python3 agent_mcp_server.pyAdd to Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"web-speed-agent": {
"command": "python3",
"args": ["/path/to/agent_mcp_server.py"],
"env": {
"WEBSPEED_API_KEY": "wsp_..."
}
}
}
}Add to Gemini CLI (~/.gemini/settings.json):
{
"mcpServers": {
"web-speed-agent": {
"command": "python3.11",
"args": ["/path/to/agent_mcp_server.py"],
"env": {
"WEBSPEED_API_KEY": "wsp_...",
"PYTHONPATH": "/path/to/web-speed-agent"
}
}
}
}Then tell the agent:
"Store my credentials for united — username me@example.com, password mypassword"
"Log into united.com and find me the cheapest flight from SFO to JFK next Friday"
Available MCP tools:
Tool | Description |
| Save login to system keychain |
| Open browser + sign in |
| Go to a URL in the active session |
| Get structured data from current page |
| Click a button or link |
| Type into a form field |
| Submit a form |
| End the browser session |
| Check API credit balance |
API reference
Agent
Agent(
api_key: str | None = None,
server_url: str | None = None,
config_dir: str = "~/.webspeed",
headless: bool = True,
)Parameter | Description |
| Web Speed API key. Falls back to |
| Override API server URL. Default: |
| Directory for config, sessions, and logs. Default: |
| Run browser headlessly. Default: |
agent.browser()
agent.browser(
session_name: str | None = None,
headless: bool | None = None,
proxy: str | None = None,
) -> ManagedBrowserReturns an async context manager. Inside the block, call .new_page() to get a Playwright Page.
Parameter | Description |
| Persist cookies to |
| Override instance |
| Proxy URL e.g. |
Session names must be alphanumeric + hyphens/underscores, max 64 chars.
agent.extract()
await agent.extract(
html: str,
page_type: str = "auto",
) -> dictSends HTML to the Web Speed API. Costs 1 credit.
Parameter | Description |
| Raw HTML string (e.g. from |
|
|
agent.map()
await agent.map(
url: str,
js: bool = False,
) -> dictFetches and extracts a public URL via the server. No local browser needed. Costs 1 credit.
Parameter | Description |
| Page URL. Must be |
| Render JavaScript before extracting. |
agent.account()
await agent.account() -> dictReturns: credits, tier, status, lifetime (total/hits/misses).
agent.store_credential()
agent.store_credential(
site: str,
username: str,
password: str,
overwrite: bool = False,
) -> NoneSaves to system keychain. Raises CredentialError if credential exists and overwrite=False.
agent.get_credential()
agent.get_credential(site: str) -> tuple[str, str] | NoneReturns (username, password) or None if not found.
agent.delete_credential()
agent.delete_credential(site: str) -> NoneRemoves credential from keychain.
Exceptions
from web_speed_agent import (
WebSpeedError, # Base exception
AuthenticationError, # Invalid/missing API key
InsufficientCreditsError, # No credits remaining
APIError, # API returned 4xx/5xx
RateLimitError, # 429 Too Many Requests
CredentialError, # Keychain error
BrowserError, # Playwright error
NetworkError, # Timeout or DNS failure
PlaywrightNotInstalledError, # Run: playwright install chromium
)from web_speed_agent import Agent, InsufficientCreditsError, NetworkError
try:
result = await agent.extract(html)
except InsufficientCreditsError:
print("Out of credits — top up at getwebspeed.io")
except NetworkError as e:
print(f"Connection failed: {e}")Configuration
Environment variables
Variable | Description |
| API key (recommended over config file) |
| Override server URL (must be |
Config file
~/.webspeed/config.yaml — created automatically on first run. Permissions set to 0o600 (owner-only).
api:
server_url: https://api.getwebspeed.io
timeout: 30
browser:
headless: trueSession files
Persisted browser sessions are stored in ~/.webspeed/sessions/<name>/storage.json.
Permissions:
0o600(owner-only)Contains: cookies, localStorage, sessionStorage
Safe to delete: agent will re-authenticate on next run
Security
What leaves your machine
When you call agent.extract(html), the page HTML is sent to the Web Speed API for processing. Everything else stays local.
Data | Where it goes |
Login credentials | Never leave your machine (system keychain only) |
Browser cookies / session | Never leave your machine (local Playwright) |
Page HTML | Sent over HTTPS to Web Speed API for extraction |
Extracted JSON | Returned to you |
HTML scrubbing (on by default)
Before any HTML is transmitted, the SDK automatically scrubs it locally:
Inline
<script>and<style>blocks removedHidden form fields with auth-related names (
csrf,token,nonce,session, etc.) have their values blankedSensitive
<meta>content attributes clearedHTML comments removed
Visible content — text, links, tables, headings, product data — is untouched.
# Default: scrubbing is on
result = await agent.extract(html)
# Turn off only if the page has no sensitive data
result = await agent.extract(html, scrub=False)
# Or scrub manually and inspect before sending
from web_speed_agent import scrub
clean_html = scrub(raw_html)
print(clean_html) # inspect what will be sent
result = await agent.extract(clean_html, scrub=False)Server-side data handling
HTML processed in-memory only — never written to disk, never logged, never cached
Auth-gated pages never cached — pages requiring login are explicitly excluded from the shared registry
Usage logs store only: a hash of your API key, a hash of the URL (or
"sdk-extract"), timestamp, and detected page type — no contentNo raw HTML in error responses — exceptions are sanitized before any error is returned
Other protections
Credentials stored in system keychain, never in files, never sent to servers
Session files written with
0o600permissions (owner-only read/write)Config directory created with
0o700permissionsTLS always verified —
verify=Trueon all HTTP calls, cannot be disabledHTTPS enforced —
server_urlmust start withhttps://, plain HTTP rejectedPath traversal prevention — session names validated against
[a-zA-Z0-9_-]allowlistNo credential logging — passwords never appear in logs or error messages
License
GNU General Public License v3.0 — see LICENSE.
Web Speed API usage is subject to the Web Speed Terms of Service.
Available Tools
17 toolsaccount_infoA
Check your Web Speed API credit balance and account status.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of disclosing behavior. The verb 'Check' suggests a read-only operation, but it does not explicitly state that it is non-destructive or whether it consumes API credits. No side effects or authentication requirements are mentioned, leaving some ambiguity.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence that is front-loaded with the verb and resource. Every word adds value, and there is no fluff or repetition of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no parameters and an existing output schema, the description is complete. It states what the tool does without needing to explain return values. The simplicity of the tool means no additional context is required for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the description does not need to explain any. The baseline for 0 params is 4, and the description adds no irrelevant parameter information, which is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'Check' and clearly identifies the resource: 'Web Speed API credit balance and account status.' It distinguishes this tool from all siblings, which are browser automation tools, making its purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage by stating what it does, but it does not explicitly say when to use it or mention alternatives. Since no sibling tool serves a similar function, explicit exclusion is unnecessary, but context like 'before making API calls' is missing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
clickA
Click an element by CSS selector.
Args: selector: CSS selector for the element to click. wait_for_navigation: Wait for a page load after clicking (default True). Set to False for clicks that trigger in-page UI changes like modals, dropdowns, or expanding sections. wait_for: CSS selector to wait for AFTER clicking — use this when the click opens a modal or triggers async UI rendering. The tool waits up to 5 s for the element to appear before returning. wait_ms: Extra milliseconds to wait after the click before reading the page. Useful for SPAs where JS hydration takes a moment (e.g. 500–2000).
| Name | Required | Description | Default |
|---|---|---|---|
| wait_ms | No | ||
| selector | Yes | ||
| wait_for | No | ||
| wait_for_navigation | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full responsibility for disclosing behavioral traits. It reveals important timing behaviors: wait_for_navigation defaults to True, wait_for waits up to 5 seconds for an element to appear, and wait_ms adds extra delay for SPA hydration. It does not mention error handling (e.g., element not found), but the disclosed timing semantics are valuable and not obvious from the schema alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: a one-sentence summary followed by a tagged list of arguments. Each parameter explanation is concise and directly useful, with no fluff. The format is scannable and front-loads the core purpose before diving into details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (4 params, one required), the description covers all key aspects: what the tool does, when to use different waiting strategies, and how to handle async UI changes. It provides enough context for an agent to invoke the tool correctly in common scenarios. The presence of an output schema means return values do not need to be described here.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage — parameters only have titles and defaults. The tool description compensates fully by explaining each parameter in detail: selector (the CSS selector), wait_for_navigation (with guidance on when to set False), wait_for (with its 5-second timeout), and wait_ms (with use cases like SPA hydration). This adds significant meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear, specific statement: 'Click an element by CSS selector.' This identifies both the action (click) and the resource (element by CSS selector), distinguishing it from sibling tools like fill_field, submit_form, and navigate. There is no ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides practical guidance on parameter usage, such as setting wait_for_navigation to False for 'clicks that trigger in-page UI changes like modals, dropdowns, or expanding sections' and using wait_for when 'the click opens a modal or triggers async UI rendering.' It does not explicitly name alternative tools, but the context for when to use this tool is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
close_browserA
Close the tab and disconnect from the browser.
In CDP mode (connected to your existing Chrome): closes the tab the agent opened and disconnects. Chrome itself stays running with all your other tabs.
In standard mode: saves the session (if named) and closes the browser.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses side effects: in CDP mode it closes the tab and disconnects but leaves Chrome running; in standard mode it saves the session (if named) and closes the browser. This is transparent and goes beyond the tool name.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured, presenting the core action first, then breaking down behavior by mode. Every sentence provides valuable information without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool, the description is complete: it explains the outcome in both operating modes, addresses session persistence, and clarifies that only the agent's tab is closed. The existence of an output schema means the return value does not need to be described.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there are no semantics to explain. The description provides necessary mode-related context that the schema (empty) cannot convey. Baseline of 4 is appropriate for a parameterless tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Close the tab and disconnect from the browser.' It distinguishes between CDP and standard modes, making the scope explicit (closes only the tab the agent opened) and differentiating it from siblings like open_browser and navigate.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains behavioral context by describing what happens in each mode (CDP vs standard), which implicitly tells the user when this tool is appropriate. It does not explicitly mention alternatives, but for a cleanup/teardown tool the usage is clear from the name and context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
evaluateA
Run JavaScript in the page context and return the result.
Use this to handle situations standard selectors can't reach:
Shadow DOM: document.querySelector('my-el').shadowRoot.querySelector('input')
Iframes: document.querySelector('iframe').contentDocument.querySelector('p')
Hidden data: window.INITIAL_DATA or JSON.parse(document.getElementById('NEXT_DATA').textContent)
Visibility checks: document.querySelector('.modal')?.getBoundingClientRect()
Triggering events: document.querySelector('input').dispatchEvent(new Event('focus'))
Args: js: JavaScript expression to evaluate. The return value is JSON-serialised and included in the response. Keep expressions simple — complex logic is better split across multiple calls.
| Name | Required | Description | Default |
|---|---|---|---|
| js | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses that the return value is JSON-serialised and included in the response, and that the JS runs in page context. However, it does not mention whether promises are awaited or if there are timeouts, so it's not fully exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with a purpose sentence, a bulleted list of example uses, and an Args section. It's longer than necessary but every section adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter tool with no annotations but an output schema, the description covers purpose, usage, and parameter semantics well. The output schema likely details the return structure, so the description's note about JSON-serialised results is sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema only says js is a string. The description explains it is a 'JavaScript expression to evaluate', notes the return value is JSON-serialised, and advises simplicity. This fully compensates for the 0% schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb+resource statement: 'Run JavaScript in the page context and return the result.' It also lists concrete use cases (Shadow DOM, iframes, hidden data) that distinguish it from sibling automation tools like click and fill_field.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly frames when to use this tool: 'Use this to handle situations standard selectors can't reach' and gives examples. It also advises to keep expressions simple, implying that complex logic should be split into multiple calls.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fill_fieldA
Type a value into a form field.
Standard mode (use_keyboard=False, default): sets the field value
directly. Works for plain <input> and <textarea> elements.
Keyboard mode (use_keyboard=True): simulates real keystrokes
(keydown → keypress → input → keyup per character). Use this for:
contenteditabledivs (X/Twitter post box, Notion, Slack, etc.)React / Vue inputs that ignore programmatic
.valuechangesSites that check for "trusted" input events to prevent botting
For X (Twitter): click the "What's happening?" box first, then call
fill_field with use_keyboard=True. This fires the React-compatible
events that enable the Post button.
Args: selector: CSS selector for the input or contenteditable element. value: Text to type. Never include \n — it will be stripped. A trailing \n is treated as Tab (advance to next field). press_tab: Press Tab after filling to move focus to the next field. use_keyboard: Simulate real keystrokes instead of direct fill. delay_ms: Milliseconds between keystrokes in keyboard mode. 0 = fast (default). Use 30–80 for sites that check typing cadence.
| Name | Required | Description | Default |
|---|---|---|---|
| value | Yes | ||
| delay_ms | No | ||
| selector | Yes | ||
| press_tab | No | ||
| use_keyboard | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full behavioral burden—and it excels. It details the simulated keystroke event sequence (keydown→keypress→input→keyup), explains that \n is stripped and a trailing \n acts as Tab, and clarifies delay_ms for sites checking typing cadence. It also reveals why keyboard mode is needed for frameworks that ignore programmatic value changes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections and bullet lists. It is moderately long but every sentence carries useful information; the X/Twitter-specific recipe is somewhat niche but relevant. No wasted words, and the layout aids scanning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (two modes, five parameters), the description is thorough. It covers behavioral edge cases (\n handling, Tab emulation), parameter semantics, and concrete use cases for modern frameworks. Since an output schema is present, not detailing return values is acceptable. An agent has everything needed to invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, but the description's Args section compensates fully. Each parameter (selector, value, press_tab, use_keyboard, delay_ms) is explained with functional meaning and edge-case behavior. For example, it notes that a trailing \n in value is treated as Tab, and recommends delay_ms 30–80 for cadence checks—details the schema cannot convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb+resource statement: 'Type a value into a form field.' It then differentiates standard mode from keyboard mode, specifying that keyboard mode is for contenteditable divs and React/Vue inputs. This establishes the tool's unique role among siblings like click and submit_form.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides strong conditional guidance: standard mode for plain inputs/textareas, keyboard mode for contenteditable/React/Vue/trusted-event checks. It even gives a specific recipe for X/Twitter. However, it does not explicitly name alternative tools to use instead, nor does it state when *not* to use this tool, so it lacks full exclusionary guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_page_infoA
Return the current page URL, title, and visible text snippet.
Useful for orientation — call this to confirm where the browser is.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Since no annotations are provided, the description carries the full burden. It clearly states the outputs (URL, title, visible text snippet) and implicitly signals a read-only, non-mutating operation. While it does not explicitly mention side effects or prerequisites, the purpose-oriented language ('confirm where the browser is') adds useful behavioral context beyond a bare description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: two sentences with no wasted words. The first sentence states the action and outputs, the second provides usage guidance. It is front-loaded and easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with an output schema, the description is nearly complete. It states what is returned and when to use it. It could mention that an active browser session is required, but the phrase 'current page' implies this. Overall, it is sufficient for an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the schema description coverage is effectively 100%. Per the rubric, 0 params warrants a baseline score of 4. The description adds no parameter details, but none are needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'Return' with concrete resources (URL, title, visible text snippet), making the tool's function clear. It also distinguishes from siblings like navigate (changes location) and read_page (likely extracts more detailed content) by framing it as an orientation helper to confirm the browser's current state.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context: 'Useful for orientation — call this to confirm where the browser is.' It explains when to use the tool but does not explicitly state when not to use it or mention alternative tools. This fits 'clear context, no exclusions' (score 4).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
loginA
Fill a login form and submit it.
Credentials: provide either site (to load from keychain) OR
username + password directly.
Selectors: if omitted, common patterns are tried automatically (input[type=email], input[name=username], etc.).
Use navigate() to go to the login page first.
| Name | Required | Description | Default |
|---|---|---|---|
| site | No | ||
| password | No | ||
| username | No | ||
| submit_selector | No | ||
| password_selector | No | ||
| username_selector | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full behavioral burden. It explains credential sources and selector auto-detection, but omits important traits like side effects (e.g., navigation after submission), error handling, or what happens if both credential modes are provided. It's adequate but not comprehensive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: purpose first, then credential options, selector behavior, and a navigation prerequisite. Every sentence is informatively dense with no fluff, earning its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (6 params, 0 required, no schema descriptions) and no annotations, the description covers essential aspects: credential modes, selector fallback, and navigation prerequisite. The output schema exists, so return values are covered elsewhere. Minor gaps like conflict resolution remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description compensates by explaining the two credential modes (site vs username/password) and the selector auto-detection logic. It adds meaning to the parameters without listing each one, but effectively ties them to usage patterns.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Fill a login form and submit it.' It specifies the resource (login form) and the action (fill and submit), distinguishing it from generic fill_field or submit_form tools by focusing on login-specific behavior and credential handling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit context: 'Use navigate() to go to the login page first' and explains credential options (site OR username/password). It doesn't name alternatives explicitly but implies the tool is for login forms, which is sufficient guidance given the sibling list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
open_browserA
Open a browser for automation.
browser — which browser to use: "chrome" (default), "firefox", or "edge".
── Chrome default behaviour ────────────────────────────────────────────────── For Chrome, CDP is tried automatically first. If the user has run 'chrome-agent' (which opens Chrome with --remote-debugging-port=9222), the agent connects to that existing window and opens a new tab — the user's real Chrome with all their logins, cookies, and extensions.
If Chrome is not running with the debug port, a helpful message is returned explaining how to start it.
── Firefox ─────────────────────────────────────────────────────────────────── Imports cookies from the user's Firefox profile (read-only) into a fresh Playwright session. Pass profile_path="auto" to detect the profile.
── Manual overrides ────────────────────────────────────────────────────────── cdp_url: connect to a specific debug URL (e.g. non-default port). profile_path: use an explicit profile directory (Chrome/Firefox/Edge). session_name: persist cookies across fresh Playwright sessions.
Args: browser: "chrome" (default), "firefox", or "edge". session_name: Cookie-persist name for standard/fresh mode. headless: Hide the window in standard/profile mode (default False). cdp_url: Override the CDP URL (default for Chrome: http://localhost:9222). profile_path: Launch with an existing browser profile ("auto" or full path).
| Name | Required | Description | Default |
|---|---|---|---|
| browser | No | ||
| cdp_url | No | ||
| headless | No | ||
| profile_path | No | ||
| session_name | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses that Chrome connects to an existing window if debug port is active, otherwise returns a helpful message, and that Firefox imports cookies read-only. However, Edge behavior is not described, leaving a transparency gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a clear one-line purpose and uses sections for readability. It is somewhat lengthy with decorative dividers, but every section contributes useful information about browser behavior and overrides.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
While parameter semantics are strong, the description omits Edge-specific behavior despite listing 'edge' as a valid browser, and it doesn't clarify whether Chrome falls back to a fresh Playwright session when the debug port is unavailable. The output schema exists, so return values need not be explained, but these gaps prevent full contextual completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description adds full semantic meaning for every parameter in the Args section, including defaults (headless=False, cdp_url=localhost:9222) and special values (browser options, profile_path='auto'). This far exceeds the schema's bare structure.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Open a browser for automation,' a specific verb+resource statement. It clearly explains browser types and distinguishes itself from siblings like navigate and close_browser by focusing on the browser lifecycle and connection behavior.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides thorough context on when to use different modes: CDP for Chrome, fresh Playwright for Firefox, and manual overrides for custom profiles and CDP URLs. It does not explicitly exclude alternatives like setup_browser, but the usage context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_pageA
Extract structured data from the current page via the Web Speed API.
Returns type-aware structured JSON: article → title, author, sections, links product → name, price, availability, specs listing → items with title, url, price, snippet other → headings, navigation, forms, text_blocks
Costs 1 Web Speed credit. Requires WEBSPEED_API_KEY.
| Name | Required | Description | Default |
|---|---|---|---|
| page_type | No | auto |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the transparency burden. It discloses the 1 Web Speed credit cost, the WEBSPEED_API_KEY requirement, and the type-aware JSON return format. It doesn't explicitly state that it's read-only, but 'extract' implies non-destructive, which adds context beyond typical minimal descriptions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured. It starts with the primary action, uses a clear bulleted list for output types, and ends with cost/auth requirements. Every sentence adds value without fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-param tool with an output schema, the description is quite complete: it explains the API source, return format, cost, and auth. The only notable gap is the lack of page_type parameter explanation, but the optional nature and default 'auto' mitigate this. Overall, it's nearly comprehensive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description does not explain the 'page_type' parameter at all. The output types (article, product, etc.) hint at possible values, but there is no explicit mapping or guidance on how page_type affects the extraction, leaving the agent to guess.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool extracts structured data from the current page, with specific output types. It is a clear, specific verb+resource, but it doesn't explicitly distinguish itself from sibling tools like get_page_info or evaluate.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage—when you need structured data from a page—but doesn't provide explicit when-to-use/when-not-to-use guidance or mention alternatives. The output type examples give some context, but no exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
setup_browserA
Set up Chrome or Edge for agent use (macOS and Windows).
Run this ONCE (with your browser closed). It:
Creates a dedicated agent profile at ~/.webspeed/chrome-debug/ (macOS) or %LOCALAPPDATA%\WebSpeedAgent\chrome-debug\ (Windows) — a non-default user data directory, which is required by Chrome before it will open the remote debugging port.
Copies your existing Chrome cookies into that profile so you are already logged into all your sites when the agent opens the browser.
macOS: installs ~/bin/chrome-agent and adds a shell alias in ~/.zshrc. Windows: writes chrome-agent.bat to your Desktop.
After setup:
macOS: type 'chrome-agent' in Terminal to open Chrome
Windows: double-click chrome-agent.bat on your Desktop
Tell the agent: open_browser(browser="chrome", cdp_url="http://localhost:9222")
The agent opens a new tab in your real Chrome with all your logins active
Re-run setup_browser() any time you want to sync fresh cookies from your main Chrome profile into the agent profile (close Chrome first).
Args: browser: "chrome" (default) or "edge".
| Name | Required | Description | Default |
|---|---|---|---|
| browser | No | chrome |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses all significant side effects: creation of a non-default user data directory, copying cookies, installing shell aliases or .bat files, and modifying .zshrc. It also warns that the browser must be closed, which is critical behavioral context. No annotations are present, so the description carries the full burden and does so comprehensively.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is relatively long but every sentence earns its place. It is well-structured with clear sections: purpose, step-by-step actions, post-setup usage, re-run instructions, and argument explanation. Information is front-loaded with the core purpose and key requirement (browser closed).
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (setup with side effects), the description covers prerequisites, exact steps, post-conditions, re-run scenarios, and the parameter. It also references the subsequent open_browser call, tying it into the broader workflow. An output schema exists, so the lack of return value discussion is acceptable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 does add meaning by stating the allowed values and default: 'browser: "chrome" (default) or "edge"'. However, it does not explain any behavioral differences between the two options, leaving some nuance undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource: 'Set up Chrome or Edge for agent use (macOS and Windows)'. It clearly distinguishes this setup tool from siblings like open_browser and navigate by explaining it creates a dedicated profile and copies cookies.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit usage guidance is provided: 'Run this ONCE (with your browser closed)' and 'Re-run setup_browser() any time you want to sync fresh cookies'. It also instructs the agent to use open_browser afterward with specific parameters, effectively indicating when this tool is a prerequisite.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
store_credentialA
Save login credentials to the system keychain (macOS/Windows/Linux).
Credentials are stored locally and NEVER sent to any server. Use site as a short identifier, e.g. "indiehackers", "twitter", "gmail".
| Name | Required | Description | Default |
|---|---|---|---|
| site | Yes | ||
| password | Yes | ||
| username | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral disclosure burden. It adds critical context that credentials are stored locally and never sent to a server, which is a key behavioral trait. Nevertheless, it does not disclose behavior for duplicate site entries or overwrites, so it is not fully transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, front-loaded with the primary purpose, and every sentence adds value: local storage claim, security guarantee, and parameter guidance. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple three-parameter keychain storage tool, the description effectively covers the main context—what it saves, where it saves it, and how to identify the site. The presence of an output schema reduces the need to explain return values, but the description could still clarify behavior for existing credentials.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, so the description must compensate. It provides a clear example for the 'site' parameter ('indiehackers', 'twitter', 'gmail') and ties the parameters together as 'login credentials.' However, it leaves 'username' and 'password' entirely to their self-explanatory names, offering no additional constraints or semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function with a specific verb and resource: 'Save login credentials to the system keychain.' It also distinguishes itself from sibling browser automation tools by specifying a local system keychain, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides context on when to use the tool—for securely storing credentials locally—and emphasizes that credentials are never sent to a server, which indirectly advises against use for server-side storage. However, it does not explicitly mention alternative tools or exclusions, so it falls short of a perfect score.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
submit_formA
Submit a form by clicking a submit button or pressing Enter.
Args: selector: CSS selector of the submit button or form. If omitted, presses Enter on the focused element.
| Name | Required | Description | Default |
|---|---|---|---|
| selector | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It transparently explains the two execution paths (clicking submit or pressing Enter) and the fallback behavior when selector is omitted. While it does not mention side effects like page navigation, the described actions are specific and unambiguous.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with a one-sentence purpose followed by an explicitly labeled argument explanation. No redundant information is present; every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool, the description covers the core action and parameter semantics fully. An output schema is present, so return values need not be explained. It could optionally mention prerequisites (e.g., a form must be present), but the tool is straightforward and adequate as is.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema only specifies 'selector' as a nullable string with a default null. The description's Args section adds essential semantics: it defines the selector as targeting a submit button or form and describes the fallback to pressing Enter when omitted. This fully compensates for the 0% schema description coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses the specific verb 'Submit' targeting a form resource, clearly distinguishing it from sibling tools like 'click' and 'fill_field'. It states the action and the two mechanisms (clicking submit button or pressing Enter), making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly defines the context for use (submitting a form) and details the behavior with and without a selector. It does not explicitly contrast with alternative tools like 'click' or mention when not to use, but the context is clear enough for an agent to choose this tool appropriately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wait_for_elementA
Wait for an element to reach a given state on the page.
Useful after an action that triggers async loading, modal opening, or element removal. Returns ok once the condition is met.
Args: selector: CSS selector for the element to watch. timeout_ms: Maximum time to wait in milliseconds (default 10 000). state: One of: 'visible' — element exists and is visible (default) 'hidden' — element exists but is hidden, or does not exist 'attached' — element is in the DOM (may be hidden) 'detached' — element has been removed from the DOM
| Name | Required | Description | Default |
|---|---|---|---|
| state | No | visible | |
| selector | Yes | ||
| timeout_ms | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It explains the return behavior ('Returns ok once the condition is met') and defines all four possible states with their semantics. It does not mention timeout error behavior, but for a simple wait operation this is adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with an intro sentence and a clear Args list. It is somewhat verbose but every detail (state definitions, timeout default) is useful. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists, the description does not need to explain return values. It covers when to use, all parameter semantics, and state behaviors. For a moderately simple wait tool, this is complete and self-sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description fully compensates by explaining each parameter: selector, timeout_ms including default, and state with all allowed values and their meanings. This adds significant value beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Wait for an element to reach a given state') on a specific resource (page element). It clearly differentiates from sibling tool 'wait_for_url' by focusing on element state rather than URL.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use the tool: 'Useful after an action that triggers async loading, modal opening, or element removal.' It does not explicitly mention alternatives or exclusions, but the context is clear enough to guide selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wait_for_urlA
Wait for the page URL to contain a given substring.
Use this after clicking a SPA navigation link where the URL changes client-side without a full page reload. Returns once the URL matches or the timeout expires.
Args: url_contains: Substring the URL must contain (e.g. '/dashboard', '?tab=posts'). timeout_ms: Maximum time to wait in milliseconds (default 10 000).
| Name | Required | Description | Default |
|---|---|---|---|
| timeout_ms | No | ||
| url_contains | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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. It states that the tool returns once the URL matches or the timeout expires, which is useful. However, it does not disclose what happens on timeout (e.g., throws an error, returns false) or other details like case sensitivity, leaving some ambiguity for a simple wait operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured. The first sentence states the core functionality, the second provides usage context, and the arguments are listed clearly. Every sentence earns its place, and there is no fluff or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has a simple scope (2 parameters, 1 required) and an output schema exists, so return value details are not needed. The description covers usage scenario, parameters, and termination behavior. A minor gap is that timeout failure behavior is not specified, but overall the description is sufficiently complete for this tool's simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides only titles with no descriptions, giving 0% schema description coverage. The description fully compensates by explaining both parameters: url_contains as the substring the URL must contain with examples, and timeout_ms as the maximum wait time in milliseconds with the default value. This adds significant meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: to wait for the page URL to contain a given substring. It specifies the resource (page URL), the condition (contains substring), and the action (wait). This distinguishes it from sibling tools like wait_for_element, which waits for a DOM element, and navigate, which changes the URL.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly advises use after clicking an SPA navigation link where the URL changes client-side without a full page reload. This provides clear context for when to use it. It implicitly excludes full-page reload scenarios but does not explicitly name an alternative tool or state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
workspace_new_slideA
Add a new slide in Google Slides (equivalent to Ctrl+M).
Drops the pointer-events lock first so the toolbar is clickable, clicks the 'New slide' button, and settles. Then call workspace_write(target='slides', placeholder=N) to fill the new slide.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Since there are no annotations, this operational detail—dropping the pointer-events lock, clicking the toolbar button, settling—discloses what the tool does beyond a mere 'adds a slide,' giving the agent context about side effects like lock state and UI interaction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, with the main purpose front-loaded and the implementation details in one concise second sentence. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with an output schema, the description fully explains the action, the behavioral prerequisites, and the recommended follow-up. It's sufficient for an agent to invoke and integrate into a workflow.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the description doesn't need to explain any. It also references the parameter for the subsequent workspace_write call, providing additional context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb+resource: 'Add a new slide in Google Slides,' and also provides the keyboard shortcut equivalent (Ctrl+M), which uniquely identifies the tool's scope among generic browser automation siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear context on the operational sequence—dropping the pointer-events lock, clicking the button, and settling—and explicitly directs the caller to use workspace_write afterwards. However, it doesn't state when not to use it or mention alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
workspace_writeA
Type text into a Google Workspace editor (Docs or Slides) reliably.
Google Docs/Slides render on , so fill_field/click can't place
text and execCommand is deprecated/flaky. This tool dismisses blocking side
panels, focuses the editor, and types with real keystrokes (the events the
canvas editor actually listens for), then verifies.
Docs: types at the current cursor (auto-removes the Gemini overlay and focuses the hidden input iframe). Slides: pass placeholder=N to pick the text box (0 = first, usually the title). Removes the onboarding modal, double-clicks the placeholder to enter edit mode, then types. Use workspace_new_slide() to add slides.
Newlines in text are sent as real Enter presses.
Args: text: Text to type. target: 'auto' (detect from URL), or force 'docs' / 'slides'. verify: Read the text back to confirm it landed (Docs only, best-effort). placeholder: Slides only — which text placeholder to edit (0-based, in document order; 0 is typically the title).
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| target | No | auto | |
| verify | No | ||
| placeholder | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses that the tool dismisses side panels, removes onboarding modals, focuses the editor, types with real keystrokes, sends newlines as Enter, and verifies the text. This goes beyond a simple 'types text' and explains underlying behavior and side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is well-organized with platform-specific subsections and a compact Args list. Every sentence adds value, covering rationale, behavior, and parameters without redundancy. It's detailed yet efficient, front-loading the core purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers why the tool exists, how it works across Docs and Slides, parameter semantics, and when to use alternatives. An output schema exists, so return values are already documented. No important context is missing for a tool of this complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description includes an Args section that explains each parameter (text, target, verify, placeholder) with platform-specific detail, e.g., placeholder=N for Slides and verify as best-effort Docs-only. This fully compensates for the schema gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: 'Type text into a Google Workspace editor (Docs or Slides) reliably.' It distinguishes itself from fill_field/click by explaining they can't place text on canvas, making the tool's niche crystal clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says fill_field/click can't place text on canvas and execCommand is deprecated/flaky, so this tool is the reliable alternative. Also references workspace_new_slide() for adding slides, providing clear when-to-use guidance and alternatives.
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. Dates show when Glama detected each change.
17 tool updates
v0.3.3- First observed
account_info - First observed
click - First observed
close_browser - First observed
evaluate - First observed
fill_field - First observed
get_page_info - First observed
login - First observed
navigate - First observed
open_browser - First observed
read_page - First observed
setup_browser - First observed
store_credential - First observed
submit_form - First observed
wait_for_element - First observed
wait_for_url - First observed
workspace_new_slide - First observed
workspace_write
TDQS
Each tool targets a distinct function: browser setup, navigation, interaction, page reading, waiting, workspace-specific actions, and JavaScript evaluation. Potential overlaps like get_page_info vs. read_page are clearly differentiated by purpose, and workspace_write vs. fill_field explicitly address different editor types.
Most tools follow a snake_case verb_noun pattern (store_credential, setup_browser, open_browser, read_page, fill_field, close_browser). Minor deviations include 'account_info' (noun_phrase), 'workspace_write' (reversed verb_noun), and 'workspace_new_slide' (noun_adjective_noun), but these remain clear and readable.
With 17 tools, the set is slightly on the heavier side but each tool serves a specific need for a browser automation agent. The count feels reasonable for the breadth of capabilities offered, including credential storage, setup, navigation, interaction, waiting, and specialized workspace support.
The toolset covers the core lifecycle of browser automation: opening, navigating, interacting, extracting data, and closing. It also includes helpful utilities like waiting and JavaScript evaluation. Minor gaps such as screenshot capture or direct dropdown selection are missing but can be worked around with existing tools.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Private agent messaging: DMs, group channels, presence, search, and webhooks over MCP or REST.
Agent communication platform for agent to agent messaging via MCP. Messages, channels, skills.
An MCP server that provides access to Agility CMS. See https://mcp.agilitycms.com for more details.
Agent-first web hosting: deploy sites, apps, databases and domains over MCP.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceReducing token usage by 70% with a deterministic mapping engine. Also links in with the Web Speed Agent SDK and MCP for post-auth agents.10GPL 3.0
- AlicenseNot gradedqualityDmaintenanceMCP Server for AI agent identity and authorization. Create, verify, and manage agent identities with trust scores and scoped authorization tokens.MIT
- AlicenseAqualityBmaintenanceProvides an MCP-native agent browser that enables autonomous agents to perceive and interact with web pages through stealth browsing, identity borrowing, and WAAP detection.15MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP-capable runtimes to read agent message rooms, sign and post public messages, and create or verify Ed25519 contribution proofs for Technocore.MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Dominic-Pi-Sunyer/web-speed-agent'
If you have feedback or need assistance with the MCP directory API, please join our Discord server