MCP server for web scraping, search, and content extraction powered by Olostep API
The Olostep MCP server demonstrates solid definition quality with comprehensive tool coverage, well-structured schemas, and extensive descriptions. All 10 tools have explicit descriptions that guide LLM selection. Input schemas are present for all tools with proper type definitions and parameter constraints. Tool names follow verb-noun convention and are action-oriented. However, output schemas are largely undocumented (response structures not defined in the tool metadata), and some parameter descriptions, while present, lack explicit constraint details (min/max, formats). Error handling guidance is minimal, tools do not document recovery paths or error categories. Tool composition is strong with clear separation of concerns (map vs crawl vs batch vs single-page scraping). The two write tools (create_crawl, batch_scrape_urls) are correctly annotated with tool annotations (readOnlyHint/destructiveHint/idempotentHint), and the server implements these annotations in code (src/index.ts lines with WRITE_TOOLS set and annotationsFor function). Descriptions are generally 50-200 chars, good for LLM-optimized prompting, though some (answers, search_web) are shorter than ideal.
Answer a factual question using web search, optionally shaped into a flat JSON object of fields (returned with sources and citations). Best for a bounded, factual answer (e.g. a company's founding year, a product's current price). It is NOT reliable for enumerating a live list from a page (e.g. 'the latest N blog posts with titles and dates'). For that, use create_map or get_webpage_content on the page and read the results instead.
Scrape a SPECIFIC, KNOWN list of URLs (typically from different domains). **Do NOT use this for crawling a website** - if the user wants to scrape a whole site or 'crawl' a domain, use `create_crawl` instead. Use this only when you already have an explicit list of URLs to scrape (e.g., user provides a CSV of URLs, or you need to scrape unrelated pages). Returns a batch_id immediately. Use `get_batch_results` with the batch_id to fetch the scraped content once the batch completes (~5–8 min). Set `wait_for_completion_seconds` to poll automatically.
**PREFERRED tool for crawling a website.** Use this whenever the user says 'crawl', 'scrape the whole site', 'get all pages from a site', or wants multiple pages from a single domain. This is the CORRECT tool for any whole-site scraping task. **Do NOT use `batch_scrape_urls` for crawling** - that tool is only for when you already have a specific list of unrelated URLs from different domains. Starts an ASYNC crawl that autonomously discovers and scrapes pages by following links from a start URL. Returns a crawl_id - the crawl runs in the background. You MUST then call `get_crawl_results` with the returned crawl_id to poll status and retrieve the scraped pages. Do NOT call `get_batch_results` with a crawl_id - crawls and batches are separate resources.
Output schemas are not documented in tool metadata. LLMs cannot plan downstream tool calls or structure extraction without knowing what fields/types to expect. For example, create_crawl returns a crawl_id, but this is stated only in description text, not in a documented output schema.
Error handling lacks recovery guidance. Tools do not document error categories (retryable vs user-fixable vs fatal) or actionable next steps. E.g., if crawl_id is invalid, what should the LLM do? Retry? Search for correct ID? Ask user?
search_web tool description is extremely brief (40 chars), below LLM-optimization baseline of 50-200 chars. Does not explain when to use vs answers tool, what result structure is, or pagination behavior.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 64 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 48 | - | v1 |
Get a LIST of URLs on a website (URL discovery only — does NOT scrape content). Use when the user wants a list of links: 'show me all URLs on this site', 'map this website', or when you want to surface candidate URLs to the user before scraping a subset. Prefer `create_crawl` if the goal is to scrape the whole site — it discovers AND scrapes in one workflow. Use this only when the URL list itself is the deliverable.
Retrieve the status and scraped content for a batch job. Pass the batch_id returned by batch_scrape_urls. If the batch is completed, returns the scraped content for each URL. If still in_progress, returns the current status so you can call again later.
Retrieve the status and scraped pages for a crawl job. Pass the crawl_id returned by create_crawl. If the crawl is still in_progress, returns the current status so you can call again later (poll every ~10 seconds). Once completed, returns the list of discovered pages with their scraped content in the requested formats. This is the REQUIRED companion to create_crawl — create_crawl only kicks off the async job, this tool is how you actually get the content.
Retrieve content of a webpage in markdown
Search and retrieve relevant URLs from a website (URL discovery only - does NOT scrape content). Use this only when the user wants a *filtered list of links* matching a search query. **Do NOT use this as a precursor to scraping** - if the user wants to scrape/crawl a site, use `create_crawl` directly.
Extract content from a single URL. Supports multiple formats and JavaScript rendering.
Search the web for information and return results with sources
Ambiguous tool separation: scrape_website and get_webpage_content are both single-URL scrapers with similar names. LLM may not understand the distinction. Description does not explain when to use one vs the other.
answers tool has implicit constraints (flat JSON only, not nested) mentioned in description but not enforced in schema. Parameter 'json' is documented as optional object but lacks schema/format specification. LLM may pass invalid nested shapes.