Skip to main content
Glama

catalyst-labs/agent-web-reader

catalyst-labs--agent-web-reader
Destructive

This tool calls the Actor "catalyst-labs/agent-web-reader" and retrieves its output results. Actor description: Tested Oct 25, 2026 on 192 live URLs: 0.92 s median per page vs 3.2 s Jina Reader, best main-text F1 (0.61 vs 0.52); search top result on-topic 85% vs 75% rag-web-browser. Headless-browser fallback for JS pages. $0.002/page, failures free.

Tool call template

This tool declares no required parameters. Add optional parameters from the input schema as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {},
    "name": "catalyst-labs--agent-web-reader"
  }
}

Input Schema

NameRequiredDescriptionDefault
urlsNoPages or PDF links to read directly (max 50 per call). Can be combined with `query`. Each URL returns exactly one row; failures come back as rows with `outcome` + `errorCode`, never as a crashed call.
queryNoWeb search query (Bing, then DuckDuckGo, then Google). The top `maxResults` results are opened and returned as markdown rows. If no search engine answers you get one row with outcome `search_blocked` (retry), if they answer with nothing `no_results`; neither is charged. Leave empty if you only pass `urls`. Example values: "apify mcp server pricing"
countryNoOptional 2-letter country code for localized search results, e.g. `us`, `gb`, `de`.
fullPageNoReturn the whole page body instead of the extracted main article. Use for list/index pages.
renderJsNo`auto` (default) retries a page in a headless browser only when the plain HTTP fetch returned no readable text, a bot check, or 403/429/503. Same $0.002 page price, charged only on success. `never` is fastest; `always` renders every HTML page. Example values: "auto"auto
waitSecsNoMax seconds (0–45, default 30) to cap the wait for the Actor run to reach terminal state. For long-running Actors the response returns at the cap with the current run status; follow `nextStep` to poll via get-actor-run. Set to 0 to fire-and-forget.
chunkSizeNoFor RAG/citations: also return `chunks` split on heading/paragraph boundaries, each with exact `tokens`, `charStart`/`charEnd` offsets into `markdown` and its `headingPath`. 0 = off (default). Same price.
maxResultsNoHow many search results to open (1-10). Default 3. Example values: 3
outputModeNo`markdown` returns the main content; `summary` returns a short lead + outline to triage many pages cheaply in tokens. Same price. Example values: "markdown"markdown
maxPdfPagesNoRead at most this many pages of each PDF. Default 50. Example values: 50
referrer_idNoReferral code from another user's receipt (ref_...). They earn 10% of this run's price as credit.
timeoutSecsNoGive up on a URL after this many seconds and return an error row for it (not charged). Default 15. Example values: 15
chunkOverlapNoCharacters repeated between consecutive chunks (starts on a word boundary). Default 200. Example values: 200
includeLinksNoKeep `[text](url)` links in the markdown. Off by default to save tokens.
buyerPublicKeyNoBase64 Ed25519 public key (SPKI). Lets you sign a useful/not useful verdict on this run's receipt for 5% off your next run.
renderBudgetSecsNoTotal time the browser fallback may spend in one call. Pages left when it runs out keep their original error row (not charged). Raise it for big batches of JavaScript-heavy URLs. Example values: 45
maxCharsPerResultNoBudget per result: markdown is cut at a paragraph boundary to this many characters. Default 6000 (about 1,600 tokens; each row reports exact `tokens`). `totalChars` and `truncated` show what was cut. Example values: 6000

Output Schema

NameRequiredDescriptionDefault
tipNoAdvisory guidance RAG Web Browser wrote to its key-value store under the reserved "TIP" key
runIdYesActor run ID
statsNoRun statistics
statusYesRun status: READY | RUNNING | TIMING-OUT | TIMED-OUT | ABORTING | ABORTED | SUCCEEDED | FAILED
actorIdYesStable Apify Actor ID from the run record
summaryYesPast-tense summary of the run state
exitCodeNoActor process exit code; populated for terminal states (especially FAILED)
nextStepYesOne primary follow-up action with identifiers interpolated
storagesYesDataset and key-value store metadata, keyed by alias. "default" is always the primary entry.
actorNameNo"username/actor-name"
startedAtNoISO timestamp when the run started
finishedAtNoISO timestamp when the run finished (terminal states only)
statusMessageNoPass-through from Apify run.statusMessage
apifyConsoleUrlNoPersonalized Apify Console link to the run; present only for Console sessions

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / description / type
      Previous value: -"string"New value: +[
      +  "string",
      +  "null"
      +]
  2. Changed1 schema field changed
    • addedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema
      Added value: +{
      +  "description": "JSON Schema for rows in the dataset at `storages.datasets.default.id` — describes row shape only; the rows themselves are NOT returned inline in this response. Inferred from this Actor's historical successful runs. To fetch actual rows, call `get-dataset-items` with the dataset id and a `fields` projection drawn from this schema.",
      +  "properties": {
      +    "chars": {
      +      "type": "number"
      +    },
      +    "contentType": {
      +      "type": "string"
      +    },
      +    "description": {
      +      "type": "string"
      +    },
      +    "errorCode": {
      +      "type": "null"
      +    },
      +    "errorMessage": {
      +      "type": "null"
      +    },
      +    "fetchedAt": {
      +      "type": "string"
      +    },
      +    "finalUrl": {
      +      "type": "string"
      +    },
      +    "httpStatus": {
      +      "type": "number"
      +    },
      +    "language": {
      +      "type": "string"
      +    },
      +    "markdown": {
      +      "type": "string"
      +    },
      +    "ms": {
      +      "type": "number"
      +    },
      +    "outcome": {
      +      "type": "string"
      +    },
      +    "publishedAt": {
      +      "type": "null"
      +    },
      +    "query": {
      +      "type": "string"
      +    },
      +    "queryMatch": {
      +      "type": "number"
      +    },
      +    "receipt_key": {
      +      "type": "string"
      +    },
      +    "receipt_verify_url": {
      +      "type": "string"
      +    },
      +    "referral_code": {
      +      "type": "string"
      +    },
      +    "retryable": {
      +      "type": "boolean"
      +    },
      +    "searchRank": {
      +      "type": "number"
      +    },
      +    "snippet": {
      +      "type": "string"
      +    },
      +    "source": {
      +      "type": "string"
      +    },
      +    "status": {
      +      "type": "string"
      +    },
      +    "title": {
      +      "type": "string"
      +    },
      +    "tokens": {
      +      "type": "number"
      +    },
      +    "totalChars": {
      +      "type": "number"
      +    },
      +    "truncated": {
      +      "type": "boolean"
      +    },
      +    "url": {
      +      "type": "string"
      +    }
      +  },
      +  "type": "object"
      +}
  3. Changed2 schema fields changed
    • addedInput schema / properties / buyerPublicKey
      Added value: +{
      +  "description": "Base64 Ed25519 public key (SPKI). Lets you sign a useful/not useful verdict on this run's receipt for 5% off your next run.",
      +  "title": "Your verdict public key (optional)",
      +  "type": "string"
      +}
    • addedInput schema / properties / referrer_id
      Added value: +{
      +  "description": "Referral code from another user's receipt (ref_...). They earn 10% of this run's price as credit.",
      +  "title": "Referral code (optional)",
      +  "type": "string"
      +}
  4. Changed3 schema fields changed
    • addedInput schema / properties / renderBudgetSecs
      Added value: +{
      +  "default": 45,
      +  "description": "Total time the browser fallback may spend in one call. Pages left when it runs out keep their original error row (not charged). Raise it for big batches of JavaScript-heavy URLs.\nExample values: 45",
      +  "examples": [
      +    45
      +  ],
      +  "title": "Browser time budget per call (seconds)",
      +  "type": "integer"
      +}
    • addedInput schema / properties / renderJs
      Added value: +{
      +  "default": "auto",
      +  "description": "`auto` (default) retries a page in a headless browser only when the plain HTTP fetch returned no readable text, a bot check, or 403/429/503. Same $0.002 page price, charged only on success. `never` is fastest; `always` renders every HTML page.\nExample values: \"auto\"",
      +  "enum": [
      +    "auto",
      +    "never",
      +    "always"
      +  ],
      +  "examples": [
      +    "auto"
      +  ],
      +  "title": "JavaScript rendering",
      +  "type": "string"
      +}
    • removedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema
      Removed value: -{
      -  "description": "JSON Schema for rows in the dataset at `storages.datasets.default.id` — describes row shape only; the rows themselves are NOT returned inline in this response. Inferred from this Actor's historical successful runs. To fetch actual rows, call `get-dataset-items` with the dataset id and a `fields` projection drawn from this schema.",
      -  "properties": {
      -    "chars": {
      -      "type": "number"
      -    },
      -    "chunkCount": {
      -      "type": "number"
      -    },
      -    "chunks": {
      -      "items": {
      -        "properties": {
      -          "charEnd": {
      -            "type": "number"
      -          },
      -          "charStart": {
      -            "type": "number"
      -          },
      -          "chars": {
      -            "type": "number"
      -          },
      -          "heading": {
      -            "type": [
      -              "null",
      -              "string"
      -            ]
      -          },
      -          "headingPath": {
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "index": {
      -            "type": "number"
      -          },
      -          "text": {
      -            "type": "string"
      -          },
      -          "tokens": {
      -            "type": "number"
      -          }
      -        },
      -        "type": "object"
      -      },
      -      "type": "array"
      -    },
      -    "contentType": {
      -      "type": "string"
      -    },
      -    "description": {
      -      "type": [
      -        "null",
      -        "string"
      -      ]
      -    },
      -    "errorCode": {
      -      "type": [
      -        "null",
      -        "string"
      -      ]
      -    },
      -    "errorMessage": {
      -      "type": [
      -        "null",
      -        "string"
      -      ]
      -    },
      -    "fetchedAt": {
      -      "type": "string"
      -    },
      -    "finalUrl": {
      -      "type": "string"
      -    },
      -    "httpStatus": {
      -      "type": "number"
      -    },
      -    "language": {
      -      "type": "string"
      -    },
      -    "markdown": {
      -      "type": [
      -        "null",
      -        "string"
      -      ]
      -    },
      -    "ms": {
      -      "type": "number"
      -    },
      -    "outcome": {
      -      "type": "string"
      -    },
      -    "publishedAt": {
      -      "type": [
      -        "null",
      -        "string"
      -      ]
      -    },
      -    "query": {
      -      "type": "string"
      -    },
      -    "queryMatch": {
      -      "type": "number"
      -    },
      -    "retryable": {
      -      "type": "boolean"
      -    },
      -    "searchRank": {
      -      "type": "number"
      -    },
      -    "snippet": {
      -      "type": "string"
      -    },
      -    "source": {
      -      "type": "string"
      -    },
      -    "status": {
      -      "type": "string"
      -    },
      -    "title": {
      -      "type": [
      -        "null",
      -        "string"
      -      ]
      -    },
      -    "tokens": {
      -      "type": "number"
      -    },
      -    "totalChars": {
      -      "type": "number"
      -    },
      -    "truncated": {
      -      "type": "boolean"
      -    },
      -    "url": {
      -      "type": "string"
      -    }
      -  },
      -  "type": "object"
      -}
  5. Changed21 schema fields changed
    • addedInput schema / properties / chunkOverlap
      Added value: +{
      +  "default": 200,
      +  "description": "Characters repeated between consecutive chunks (starts on a word boundary). Default 200.\nExample values: 200",
      +  "examples": [
      +    200
      +  ],
      +  "title": "Chunk overlap (characters)",
      +  "type": "integer"
      +}
    • addedInput schema / properties / chunkSize
      Added value: +{
      +  "default": 0,
      +  "description": "For RAG/citations: also return `chunks` split on heading/paragraph boundaries, each with exact `tokens`, `charStart`/`charEnd` offsets into `markdown` and its `headingPath`. 0 = off (default). Same price.",
      +  "title": "Chunk size (characters)",
      +  "type": "integer"
      +}
    • changedInput schema / properties / maxCharsPerResult / description
      Previous value: -"Token budget: each result's markdown is cut at a paragraph boundary to this many characters (about 4 characters = 1 token). Default 6000 (~1,500 tokens). `totalChars` and `truncated` tell you what was cut.\nExample values: 6000"New value: +"Budget per result: markdown is cut at a paragraph boundary to this many characters. Default 6000 (about 1,600 tokens; each row reports exact `tokens`). `totalChars` and `truncated` show what was cut.\nExample values: 6000"
    • changedInput schema / properties / query / description
      Previous value: -"Web search query. The top `maxResults` results are opened and returned as markdown. Leave empty if you only pass `urls`.\nExample values: \"apify mcp server pricing\""New value: +"Web search query (Bing, then DuckDuckGo, then Google). The top `maxResults` results are opened and returned as markdown rows. If no search engine answers you get one row with outcome `search_blocked` (retry), if they answer with nothing `no_results`; neither is charged. Leave empty if you only pass `urls`.\nExample values: \"apify mcp server pricing\""
    • changedInput schema / properties / urls / description
      Previous value: -"Pages or PDF links to read directly (max 50). Can be combined with `query`."New value: +"Pages or PDF links to read directly (max 50 per call). Can be combined with `query`. Each URL returns exactly one row; failures come back as rows with `outcome` + `errorCode`, never as a crashed call."
    • changedInput schema / properties / urls / items / description
      Previous value: -"Pages or PDF links to read directly (max 50). Can be combined with `query`."New value: +"Pages or PDF links to read directly (max 50 per call). Can be combined with `query`. Each URL returns exactly one row; failures come back as rows with `outcome` + `errorCode`, never as a crashed call."
    • addedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / chunkCount
      Added value: +{
      +  "type": "number"
      +}
    • addedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / chunks
      Added value: +{
      +  "items": {
      +    "properties": {
      +      "charEnd": {
      +        "type": "number"
      +      },
      +      "charStart": {
      +        "type": "number"
      +      },
      +      "chars": {
      +        "type": "number"
      +      },
      +      "heading": {
      +        "type": [
      +          "null",
      +          "string"
      +        ]
      +      },
      +      "headingPath": {
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "index": {
      +        "type": "number"
      +      },
      +      "text": {
      +        "type": "string"
      +      },
      +      "tokens": {
      +        "type": "number"
      +      }
      +    },
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / description / type
      Previous value: -"null"New value: +[
      +  "null",
      +  "string"
      +]
    • changedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / errorCode / type
      Previous value: -"null"New value: +[
      +  "null",
      +  "string"
      +]
    • changedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / errorMessage / type
      Previous value: -"null"New value: +[
      +  "null",
      +  "string"
      +]
    • changedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / markdown / type
      Previous value: -"string"New value: +[
      +  "null",
      +  "string"
      +]
    • addedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / outcome
      Added value: +{
      +  "type": "string"
      +}
    • changedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / publishedAt / type
      Previous value: -"null"New value: +[
      +  "null",
      +  "string"
      +]
    • addedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / query
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / queryMatch
      Added value: +{
      +  "type": "number"
      +}
    • addedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / retryable
      Added value: +{
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / searchRank
      Added value: +{
      +  "type": "number"
      +}
    • addedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / snippet
      Added value: +{
      +  "type": "string"
      +}
    • changedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / title / type
      Previous value: -"string"New value: +[
      +  "null",
      +  "string"
      +]
    • addedOutput schema / properties / storages / properties / datasets / properties / default / properties / itemsSchema / properties / tokens
      Added value: +{
      +  "type": "number"
      +}
  6. First observed

TDQS

C2.8/5.0
Behavior3/5

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

The description adds genuinely useful context absent from annotations: $0.002/page, failures free, headless-browser fallback for JS pages. However, annotations declare readOnlyHint=false and destructiveHint=true, and the description never explains what that means (it spawns a billable actor run), nor mentions any auth or run-status polling behavior. Partial credit for the pricing disclosure.

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

Conciseness3/5

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

It is short and front-loads the fact that this wraps an Actor call, which is the right lead. But the second sentence is a wall of vendor benchmark numbers that do not help an agent decide or call correctly, so much of the content does not earn its place.

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

Completeness3/5

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

With 17 optional parameters, a rich schema, and an output schema, the description can lean on structured fields. Still, a dual-mode tool (URL reading vs web search) with per-URL failure rows and a waitSecs/get-actor-run polling path deserves at least a one-line framing of its modes, which is missing.

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% with detailed per-parameter text (urls, query, renderJs, chunkSize, outputMode, timeouts), so the schema carries all parameter meaning. The description adds nothing parameter-specific, which is the expected baseline case when coverage is complete.

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

Purpose3/5

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

The description states it calls the Actor "catalyst-labs/agent-web-reader" and retrieves results, and the Actor blurb hints at page reading, main-text extraction, search, and JS fallback. But the actual job — fetch URLs / run a web search and return markdown rows — is never stated plainly; it is buried under benchmark stats (0.92 s vs 3.2 s, F1 0.61 vs 0.52). The purpose is inferable rather than explicit.

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

Usage Guidelines2/5

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

Nothing says when to use this versus another tool, or when not to. The two operating modes (pass `urls` to read, `query` to search) are only discoverable from the schema, and there is no guidance on choosing between them or on cost trade-offs. Siblings are generic actor-run utilities, so conflict is low, but no routing guidance is offered.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.