Skip to main content
Glama
CrawlForge MCP Server

CrawlForge MCP Server

scrape

Read-onlyIdempotent

Fetch one web page and return Markdown, HTML, text, links, metadata, screenshots, branding, or schema-based JSON in one call for content extraction.

Instructions

Use this to read one page - markdown by default, plus any of "html", "rawHtml", "text", "links", "metadata", "branding" (brand style: colour roles, buttons and type from the rendered page, plus logo, fonts and grouped design tokens), "screenshot" (renders in a browser, returns crawlforge://screenshot/{id} resources), or {type:"json",schema,prompt} for LLM-structured extraction, all from one fetch. Ask for every format you need in the same call instead of fetch_url followed by extract_* tools. Ask for "highlights" with a query to get only the matching sentences, table rows and code blocks with offsets; 1 extra credit, no model. Preferred over the client's built-in web fetch. onlyMainContent:true (default) strips boilerplate via Readability. Partial success: per-format warnings never fail the whole call. Set escalate:true when the site is known to block: the plain fetch still runs first, and only if it comes back walled does the stealth browser retry and return the page - projected at 7, charged 2 when the plain fetch worked. Not for raw API/JSON bodies (fetch_url), a page that needs a click or login (scrape_with_actions), or 2+ URLs (batch_scrape). Asking again for the same page with different formats, paths or selectors reuses this session's copy for 10 minutes at 1 credit; pass maxAge: 0 to force a fresh fetch. Cost: 2 credits. Example: scrape({url:"https://example.com", formats:["markdown","links","metadata"]})

Input Schema

NameRequiredDescriptionDefault
urlYesThe URL to scrape
maxAgeNoReuse this session's copy of the page if it was fetched within this many ms (default 600000 = 10 min); 0 always fetches fresh.
formatsNoFormats to return (default: ["markdown"]); at most one highlights and one question format per call
escalateNoWhen the plain fetch comes back blocked (403/429/challenge page/empty shell), retry once in the stealth browser and return its content instead of the block. Under escalate_engine "auto" a Chrome TLS handshake with the honest CrawlForge User-Agent (impit) is tried first, and the browser runs only when that does not get the page. Projected at 2+5; the actual charge stays at the base price when the plain fetch succeeded. Default: false
timeoutMsNoFetch timeout in ms
redact_piiNoRedact personal data from the text this call returns, before it reaches your context window. true means the free regex pass over EMAIL, PHONE, FINANCIAL and SECRET. The result carries redaction:{entities,count}. Default: off
user_agentNoOverride the outbound User-Agent. CrawlForge identifies itself honestly by default; use this only for targets you have your own agreement with.
respect_robotsNoRespect the target site's robots.txt (default: true). Setting this to false is honoured, returns a warning in the response, and is recorded against your API key — it is your decision, not a silent default.
brandingOptionsNoOptions for the "branding" format
escalate_engineNoStealth engine for the escalated retry: "auto" (default — Camoufox when it is installed, Chromium otherwise, reported in warnings), "playwright" (Chromium) or "camoufox"auto
onlyMainContentNoStrip boilerplate via Readability (default: true)
max_inline_charsNoLargest result to return inline, in characters of its JSON. Over it, the call returns a preview plus a result_handle for read_result instead of the whole result (default 40,000; env CRAWLFORGE_MAX_INLINE_CHARS)
screenshotOptionsNoOptions for the "screenshot" format

Output Schema

NameRequiredDescriptionDefault
urlNoFinal URL after redirects
viewNoWhether preview and read_result offsets index a text field or the pretty-printed JSON
_costNoCost-transparency metadata (D3.5): what this call was projected to cost and what it was charged
cacheNoPage cache: whether this call reused a copy of the page fetched earlier in the session
errorNoWhy success is false: a challenge page, an empty shell or an error placeholder was served instead of the content
titleNoDocument title; present when success is false
statusNoHTTP status of the fetch; present when success is false
blockedNoPresent when a bot-defence vendor served a challenge page; the fallback hint names the tool to try next
contentNoOne key per requested format
previewNoThe first max_inline_chars characters of the view named by view_path (or of the pretty-printed JSON)
stealthNoPresent when escalated is true: the stealth engine that ran ("impit" when the Chrome TLS handshake got the page without a browser), and the bot-defence vendor the plain fetch hit (null when the block named none)
successNoWhether the scrape completed
warningsNoPer-format warnings; partial success never fails the whole call
escalatedNoPresent only when escalate:true was passed: whether the blocked plain fetch was retried in the stealth browser. False means the plain fetch sufficed and the call is charged at the base price
next_stepNoFailed calls only: the tool or fix to try next
redactionNoPresent when redact_pii was set: what was redacted from the text of this result
truncatedNoTrue when the inline result is a preview
view_pathNoDotted path of the text field the view was cut from; null for the JSON view
expires_atNoWhen the stored result is dropped (ISO 8601)
total_charsNoLength of the full view in characters
result_handleNoHandle for read_result; the full result is kept 1 hour

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changedv6.25.0
    • addedInput schema / properties / brandingOptions / properties / computeStyles
      Added value: +{
      +  "default": true,
      +  "description": "Render the page and read computed styles for colour roles, buttons and type (default: true; false keeps branding to the HTML and CSS)",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / brandingOptions / properties / dtcg
      Added value: +{
      +  "default": false,
      +  "description": "Also return the tokens as W3C Design Tokens (DTCG 2025.10) JSON, under dtcg",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / brandingOptions / properties / rawVariables
      Added value: +{
      +  "default": false,
      +  "description": "Also return every CSS custom property as found, under cssVariables (large on design-system sites)",
      +  "type": "boolean"
      +}
    • changedOutput schema / properties / content / properties / branding / description
      Previous value: -"Static design tokens: colors, fonts, logo"New value: +"Brand style: colour roles, button components and type (computed or inferred), logo, fonts and grouped design tokens"
  2. Changed5 schema fields changedv6.24.0
    • addedInput schema / properties / maxAge
      Added value: +{
      +  "description": "Reuse this session's copy of the page if it was fetched within this many ms (default 600000 = 10 min); 0 always fetches fresh.",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • changedOutput schema / properties / _cost / description
      Previous value: -"Cost-transparency metadata (D3.5), present when injected into the text copy of the result"New value: +"Cost-transparency metadata (D3.5): what this call was projected to cost and what it was charged"
    • changedOutput schema / properties / _cost / properties / actual / description
      Previous value: -"Credits actually charged (0 in creator mode, half-rate on error)"New value: +"Credits actually charged (0 in creator mode, and 0 for a failed call)"
    • addedOutput schema / properties / cache
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Page cache: whether this call reused a copy of the page fetched earlier in the session",
      +  "properties": {
      +    "ageMs": {
      +      "description": "Age of that copy in ms",
      +      "type": [
      +        "number",
      +        "null"
      +      ]
      +    },
      +    "fetchedAt": {
      +      "description": "When the oldest page used was fetched (ISO 8601)",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "note": {
      +      "description": "Hits only: how old the copy is and how to force a fresh fetch",
      +      "type": "string"
      +    },
      +    "state": {
      +      "description": "hit: every page came from this session's copy; bypass: fetched fresh on request (maxAge 0) or not cacheable; miss: fetched",
      +      "enum": [
      +        "hit",
      +        "miss",
      +        "bypass"
      +      ],
      +      "type": "string"
      +    }
      +  },
      +  "type": "object"
      +}
    • addedOutput schema / properties / next_step
      Added value: +{
      +  "description": "Failed calls only: the tool or fix to try next",
      +  "type": "string"
      +}
  3. Changed7 schema fields changedv6.19.2
    • changedInput schema / properties / formats / description
      Previous value: -"Formats to return (default: [\"markdown\"])"New value: +"Formats to return (default: [\"markdown\"]); at most one highlights and one question format per call"
    • addedOutput schema / properties / content / properties / answer / properties / evidence / items / properties / kind / description
      Added value: +"\"heading\" occurs only in question evidence"
    • changedOutput schema / properties / content / properties / answer / properties / evidence / items / properties / kind / enum
      Previous value: -[
      -  "sentence",
      -  "table_row",
      -  "code_block"
      -]New value: +[
      +  "sentence",
      +  "table_row",
      +  "code_block",
      +  "heading"
      +]
    • changedOutput schema / properties / content / properties / answer / properties / grounded / description
      Previous value: -"True when every number and proper noun in text appears in the evidence or the question; always true in extractive mode"New value: +"False when no unit matched (text is empty) or, in model mode, when the model found no answer in the evidence (text is empty) or used a number or proper noun that appears in neither the evidence nor the question"
    • addedOutput schema / properties / content / properties / highlights / items / properties / kind / description
      Added value: +"\"heading\" occurs only in question evidence"
    • changedOutput schema / properties / content / properties / highlights / items / properties / kind / enum
      Previous value: -[
      -  "sentence",
      -  "table_row",
      -  "code_block"
      -]New value: +[
      +  "sentence",
      +  "table_row",
      +  "code_block",
      +  "heading"
      +]
    • addedOutput schema / properties / content / properties / metadata / properties / title / description
      Added value: +"The document <title>; og:title, then the first H1, only when the page has none. og:title itself is og_tags.title"
  4. Changed2 schema fields changedv6.14.0
    • changedInput schema / properties / escalate / description
      Previous value: -"When the plain fetch comes back blocked (403/429/challenge page/empty shell), retry once in the stealth browser and return its content instead of the block. Projected at 2+5; the actual charge stays at the base price when the plain fetch succeeded. Default: false"New value: +"When the plain fetch comes back blocked (403/429/challenge page/empty shell), retry once in the stealth browser and return its content instead of the block. Under escalate_engine \"auto\" a Chrome TLS handshake with the honest CrawlForge User-Agent (impit) is tried first, and the browser runs only when that does not get the page. Projected at 2+5; the actual charge stays at the base price when the plain fetch succeeded. Default: false"
    • changedOutput schema / properties / stealth / description
      Previous value: -"Present when escalated is true: the stealth engine that ran, and the bot-defence vendor the plain fetch hit (null when the block named none)"New value: +"Present when escalated is true: the stealth engine that ran (\"impit\" when the Chrome TLS handshake got the page without a browser), and the bot-defence vendor the plain fetch hit (null when the block named none)"
  5. Changed3 schema fields changedv6.8.0
    • changedInput schema / properties / escalate_engine / default
      Previous value: -"playwright"New value: +"auto"
    • changedInput schema / properties / escalate_engine / description
      Previous value: -"Stealth engine for the escalated retry (default: \"playwright\")"New value: +"Stealth engine for the escalated retry: \"auto\" (default — Camoufox when it is installed, Chromium otherwise, reported in warnings), \"playwright\" (Chromium) or \"camoufox\""
    • changedInput schema / properties / escalate_engine / enum
      Previous value: -[
      -  "playwright",
      -  "camoufox"
      -]New value: +[
      +  "auto",
      +  "playwright",
      +  "camoufox"
      +]
  6. Changed33 schema fields changedv6.0.0
    • removedInput schema / additionalProperties
      Removed value: -false
    • removedInput schema / properties / brandingOptions / additionalProperties
      Removed value: -false
    • addedInput schema / properties / escalate
      Added value: +{
      +  "default": false,
      +  "description": "When the plain fetch comes back blocked (403/429/challenge page/empty shell), retry once in the stealth browser and return its content instead of the block. Projected at 2+5; the actual charge stays at the base price when the plain fetch succeeded. Default: false",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / escalate_engine
      Added value: +{
      +  "default": "playwright",
      +  "description": "Stealth engine for the escalated retry (default: \"playwright\")",
      +  "enum": [
      +    "playwright",
      +    "camoufox"
      +  ],
      +  "type": "string"
      +}
    • changedInput schema / properties / formats / items / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "markdown",
      -      "html",
      -      "rawHtml",
      -      "text",
      -      "links",
      -      "metadata",
      -      "screenshot",
      -      "branding"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "prompt": {
      -        "description": "Extraction instruction for the LLM",
      -        "type": "string"
      -      },
      -      "schema": {
      -        "additionalProperties": {},
      -        "description": "JSON schema for extraction",
      -        "type": "object"
      -      },
      -      "type": {
      -        "const": "json",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "markdown",
      +      "html",
      +      "rawHtml",
      +      "text",
      +      "links",
      +      "metadata",
      +      "screenshot",
      +      "branding"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "properties": {
      +      "prompt": {
      +        "description": "Extraction instruction for the LLM",
      +        "type": "string"
      +      },
      +      "schema": {
      +        "additionalProperties": {},
      +        "description": "JSON schema for extraction",
      +        "propertyNames": {
      +          "type": "string"
      +        },
      +        "type": "object"
      +      },
      +      "type": {
      +        "const": "json",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "max_highlights": {
      +        "default": 10,
      +        "description": "How many units to return (default 10)",
      +        "maximum": 50,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "mode": {
      +        "default": "extractive",
      +        "description": "\"extractive\" (default) returns verbatim page text, no model; \"model\" adds an LLM step (+3 credits)",
      +        "enum": [
      +          "extractive",
      +          "model"
      +        ],
      +        "type": "string"
      +      },
      +      "query": {
      +        "description": "What to look for; the matching sentences, table rows and code blocks come back verbatim with offsets into the markdown",
      +        "maxLength": 500,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "highlights",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "query"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "mode": {
      +        "default": "extractive",
      +        "description": "\"extractive\" (default) returns verbatim page text, no model; \"model\" adds an LLM step (+3 credits)",
      +        "enum": [
      +          "extractive",
      +          "model"
      +        ],
      +        "type": "string"
      +      },
      +      "question": {
      +        "description": "The question to answer from the page; the evidence units come back verbatim with offsets",
      +        "maxLength": 500,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "question",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "question"
      +    ],
      +    "type": "object"
      +  }
      +]
    • addedInput schema / properties / max_inline_chars
      Added value: +{
      +  "description": "Largest result to return inline, in characters of its JSON. Over it, the call returns a preview plus a result_handle for read_result instead of the whole result (default 40,000; env CRAWLFORGE_MAX_INLINE_CHARS)",
      +  "maximum": 10000000,
      +  "minimum": 1000,
      +  "type": "integer"
      +}
    • addedInput schema / properties / redact_pii
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "boolean"
      +    },
      +    {
      +      "properties": {
      +        "entities": {
      +          "description": "Which classes to redact, case-insensitive: EMAIL, PHONE, FINANCIAL, SECRET, plus PERSON and LOCATION when mode is \"model\". Omitted or empty means all four regex classes (and both model classes in \"model\" mode). An unknown name, or a model-only name without mode:\"model\", is rejected",
      +          "items": {
      +            "type": "string"
      +          },
      +          "type": "array"
      +        },
      +        "mode": {
      +          "description": "\"fast\" (default) is regex only and free; \"model\" adds an Ollama NER pass for PERSON and LOCATION (+3 credits once per call)",
      +          "enum": [
      +            "fast",
      +            "model"
      +          ],
      +          "type": "string"
      +        },
      +        "replace_style": {
      +          "description": "\"tag\" (default) writes <EMAIL>, \"mask\" writes [REDACTED], \"remove\" deletes the value",
      +          "enum": [
      +            "tag",
      +            "mask",
      +            "remove"
      +          ],
      +          "type": "string"
      +        }
      +      },
      +      "type": "object"
      +    }
      +  ],
      +  "description": "Redact personal data from the text this call returns, before it reaches your context window. true means the free regex pass over EMAIL, PHONE, FINANCIAL and SECRET. The result carries redaction:{entities,count}. Default: off"
      +}
    • removedInput schema / properties / screenshotOptions / additionalProperties
      Removed value: -false
    • changedOutput schema / properties / _cost / additionalProperties
      Previous value: -trueNew value: +{}
    • addedOutput schema / properties / blocked
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Present when a bot-defence vendor served a challenge page; the fallback hint names the tool to try next",
      +  "properties": {
      +    "evidence": {
      +      "type": "string"
      +    },
      +    "vendor": {
      +      "type": "string"
      +    }
      +  },
      +  "type": "object"
      +}
    • changedOutput schema / properties / content / additionalProperties
      Previous value: -trueNew value: +{}
    • addedOutput schema / properties / content / properties / answer
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Result of the {type:\"question\"} format",
      +  "properties": {
      +    "evidence": {
      +      "description": "The units the answer rests on, verbatim with offsets",
      +      "items": {
      +        "additionalProperties": {},
      +        "properties": {
      +          "kind": {
      +            "enum": [
      +              "sentence",
      +              "table_row",
      +              "code_block"
      +            ],
      +            "type": "string"
      +          },
      +          "length": {
      +            "type": "number"
      +          },
      +          "offset": {
      +            "description": "JS string index into the markdown format of this call",
      +            "type": "number"
      +          },
      +          "score": {
      +            "description": "BM25 relevance to the query, higher is better",
      +            "type": "number"
      +          },
      +          "text": {
      +            "description": "Verbatim page text: markdown.slice(offset, offset + length) === text",
      +            "type": "string"
      +          }
      +        },
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "grounded": {
      +      "description": "True when every number and proper noun in text appears in the evidence or the question; always true in extractive mode",
      +      "type": "boolean"
      +    },
      +    "text": {
      +      "description": "Extractive mode: the evidence texts joined; model mode: the model's answer",
      +      "type": "string"
      +    }
      +  },
      +  "type": "object"
      +}
    • addedOutput schema / properties / content / properties / branding / propertyNames
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / content / properties / highlights
      Added value: +{
      +  "description": "Result of the {type:\"highlights\"} format: the units matching the query, best first, verbatim with offsets",
      +  "items": {
      +    "additionalProperties": {},
      +    "properties": {
      +      "kind": {
      +        "enum": [
      +          "sentence",
      +          "table_row",
      +          "code_block"
      +        ],
      +        "type": "string"
      +      },
      +      "length": {
      +        "type": "number"
      +      },
      +      "offset": {
      +        "description": "JS string index into the markdown format of this call",
      +        "type": "number"
      +      },
      +      "score": {
      +        "description": "BM25 relevance to the query, higher is better",
      +        "type": "number"
      +      },
      +      "text": {
      +        "description": "Verbatim page text: markdown.slice(offset, offset + length) === text",
      +        "type": "string"
      +      }
      +    },
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / properties / content / properties / links / additionalProperties
      Previous value: -trueNew value: +{}
    • changedOutput schema / properties / content / properties / links / properties / links / items / additionalProperties
      Previous value: -trueNew value: +{}
    • changedOutput schema / properties / content / properties / metadata / additionalProperties
      Previous value: -trueNew value: +{}
    • addedOutput schema / properties / content / properties / metadata / properties / og_tags / propertyNames
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / content / properties / metadata / properties / twitter_tags / propertyNames
      Added value: +{
      +  "type": "string"
      +}
    • changedOutput schema / properties / content / properties / screenshots / items / additionalProperties
      Previous value: -trueNew value: +{}
    • addedOutput schema / properties / error
      Added value: +{
      +  "description": "Why success is false: a challenge page, an empty shell or an error placeholder was served instead of the content",
      +  "type": "string"
      +}
    • addedOutput schema / properties / escalated
      Added value: +{
      +  "description": "Present only when escalate:true was passed: whether the blocked plain fetch was retried in the stealth browser. False means the plain fetch sufficed and the call is charged at the base price",
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / expires_at
      Added value: +{
      +  "description": "When the stored result is dropped (ISO 8601)",
      +  "type": "string"
      +}
    • addedOutput schema / properties / preview
      Added value: +{
      +  "description": "The first max_inline_chars characters of the view named by view_path (or of the pretty-printed JSON)",
      +  "type": "string"
      +}
    • addedOutput schema / properties / redaction
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Present when redact_pii was set: what was redacted from the text of this result",
      +  "properties": {
      +    "count": {
      +      "description": "Total spans replaced",
      +      "type": "number"
      +    },
      +    "entities": {
      +      "additionalProperties": {
      +        "type": "number"
      +      },
      +      "description": "How many spans were replaced, by entity class; a class with no hits is omitted",
      +      "propertyNames": {
      +        "type": "string"
      +      },
      +      "type": "object"
      +    },
      +    "mode": {
      +      "description": "\"fast\" is the free regex pass; \"model\" added an Ollama NER pass for PERSON and LOCATION",
      +      "enum": [
      +        "fast",
      +        "model"
      +      ],
      +      "type": "string"
      +    },
      +    "model_ran": {
      +      "description": "mode \"model\" only: whether a model actually answered. False means no LLM route existed and the model surcharge was not charged",
      +      "type": "boolean"
      +    }
      +  },
      +  "type": "object"
      +}
    • addedOutput schema / properties / result_handle
      Added value: +{
      +  "description": "Handle for read_result; the full result is kept 1 hour",
      +  "type": "string"
      +}
    • addedOutput schema / properties / status
      Added value: +{
      +  "description": "HTTP status of the fetch; present when success is false",
      +  "type": "number"
      +}
    • addedOutput schema / properties / stealth
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Present when escalated is true: the stealth engine that ran, and the bot-defence vendor the plain fetch hit (null when the block named none)",
      +  "properties": {
      +    "engine": {
      +      "type": "string"
      +    },
      +    "vendor_detected": {
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    }
      +  },
      +  "type": "object"
      +}
    • addedOutput schema / properties / title
      Added value: +{
      +  "description": "Document title; present when success is false",
      +  "type": "string"
      +}
    • addedOutput schema / properties / total_chars
      Added value: +{
      +  "description": "Length of the full view in characters",
      +  "type": "number"
      +}
    • addedOutput schema / properties / truncated
      Added value: +{
      +  "description": "True when the inline result is a preview",
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / view
      Added value: +{
      +  "description": "Whether preview and read_result offsets index a text field or the pretty-printed JSON",
      +  "enum": [
      +    "text",
      +    "json"
      +  ],
      +  "type": "string"
      +}
    • addedOutput schema / properties / view_path
      Added value: +{
      +  "description": "Dotted path of the text field the view was cut from; null for the JSON view",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
  7. Changed2 schema fields changedv5.4.0
    • addedInput schema / properties / respect_robots
      Added value: +{
      +  "description": "Respect the target site's robots.txt (default: true). Setting this to false is honoured, returns a warning in the response, and is recorded against your API key — it is your decision, not a silent default.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / user_agent
      Added value: +{
      +  "description": "Override the outbound User-Agent. CrawlForge identifies itself honestly by default; use this only for targets you have your own agreement with.",
      +  "type": "string"
      +}
  8. Changed2 schema fields changedv5.0.4
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$schema": "https://json-schema.org/draft/2020-12/schema",
      +  "additionalProperties": false,
      +  "properties": {
      +    "_cost": {
      +      "additionalProperties": true,
      +      "description": "Cost-transparency metadata (D3.5), present when injected into the text copy of the result",
      +      "properties": {
      +        "actual": {
      +          "description": "Credits actually charged (0 in creator mode, half-rate on error)",
      +          "type": "number"
      +        },
      +        "projected": {
      +          "description": "Credits projected for this call before execution",
      +          "type": "number"
      +        },
      +        "projection_note": {
      +          "description": "Human-readable note about how the cost was projected",
      +          "type": "string"
      +        },
      +        "remaining_credits": {
      +          "description": "Credits remaining on the account after this call, if known",
      +          "type": [
      +            "number",
      +            "null"
      +          ]
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "content": {
      +      "additionalProperties": true,
      +      "description": "One key per requested format",
      +      "properties": {
      +        "branding": {
      +          "additionalProperties": {},
      +          "description": "Static design tokens: colors, fonts, logo",
      +          "type": "object"
      +        },
      +        "html": {
      +          "type": "string"
      +        },
      +        "json": {
      +          "description": "Result of the {type:\"json\"} format (LLM-structured extraction)"
      +        },
      +        "links": {
      +          "additionalProperties": true,
      +          "properties": {
      +            "external_count": {
      +              "type": "number"
      +            },
      +            "internal_count": {
      +              "type": "number"
      +            },
      +            "links": {
      +              "items": {
      +                "additionalProperties": true,
      +                "properties": {
      +                  "href": {
      +                    "type": "string"
      +                  },
      +                  "is_external": {
      +                    "type": "boolean"
      +                  },
      +                  "original_href": {
      +                    "type": "string"
      +                  },
      +                  "text": {
      +                    "type": "string"
      +                  }
      +                },
      +                "type": "object"
      +              },
      +              "type": "array"
      +            },
      +            "total_count": {
      +              "type": "number"
      +            }
      +          },
      +          "type": "object"
      +        },
      +        "markdown": {
      +          "type": "string"
      +        },
      +        "metadata": {
      +          "additionalProperties": true,
      +          "properties": {
      +            "author": {
      +              "type": "string"
      +            },
      +            "canonical_url": {
      +              "type": "string"
      +            },
      +            "description": {
      +              "type": "string"
      +            },
      +            "json_ld": {
      +              "items": {},
      +              "type": "array"
      +            },
      +            "keywords": {
      +              "items": {
      +                "type": "string"
      +              },
      +              "type": "array"
      +            },
      +            "microdata": {
      +              "items": {},
      +              "type": "array"
      +            },
      +            "og_tags": {
      +              "additionalProperties": {},
      +              "type": "object"
      +            },
      +            "robots": {
      +              "type": "string"
      +            },
      +            "title": {
      +              "type": "string"
      +            },
      +            "twitter_tags": {
      +              "additionalProperties": {},
      +              "type": "object"
      +            },
      +            "url": {
      +              "type": "string"
      +            },
      +            "viewport": {
      +              "type": "string"
      +            }
      +          },
      +          "type": "object"
      +        },
      +        "rawHtml": {
      +          "type": "string"
      +        },
      +        "screenshots": {
      +          "description": "Present for the \"screenshot\" format; each item carries a resourceUri once published",
      +          "items": {
      +            "additionalProperties": true,
      +            "properties": {},
      +            "type": "object"
      +          },
      +          "type": "array"
      +        },
      +        "text": {
      +          "type": "string"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "success": {
      +      "description": "Whether the scrape completed",
      +      "type": "boolean"
      +    },
      +    "url": {
      +      "description": "Final URL after redirects",
      +      "type": "string"
      +    },
      +    "warnings": {
      +      "description": "Per-format warnings; partial success never fails the whole call",
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    }
      +  },
      +  "type": "object"
      +}
  9. First observedv4.10.0

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, open-world, non-destructive behavior, and the description adds material context beyond them: cost is 2 credits, cached reuse lasts 10 minutes at 1 credit, per-format warnings do not fail the whole call, and escalate runs plain fetch first then retries in stealth only if blocked. These details are exactly the behavioral traits an agent needs before invoking a multi-format scrape.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose and alternatives, and nearly every sentence carries operational information. It is long and dense, with some overstuffed parentheticals around branding and escalation, but it avoids obvious filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With annotations, a full input schema, and an output schema, the description provides enough context for correct invocation: format behavior, cost, caching, escalation fallback, partial success, and sibling alternatives are all covered. Nothing critical is missing for an agent choosing and calling this complex tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 13 parameters in detail. The description adds some useful emphasis around formats, escalate, and maxAge, but it mostly repeats selected schema semantics and does not attempt to cover the full parameter set, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: read one page, with markdown by default plus named formats. It also distinguishes the tool from siblings by saying it is preferred over the client's built-in fetch and should be used instead of fetch_url followed by extract_* tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-not guidance: not for raw API/JSON bodies (fetch_url), a page needing click/login (scrape_with_actions), or 2+ URLs (batch_scrape). It also states when to use escalate:true and when to combine formats in one call rather than making separate fetch/extract calls.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.