String Web Access
Server Details
Search the web, fetch any URL and map a site as clean, LLM-ready Markdown.
- Status
- Healthy
- Uptime
- 100.0% over the last 24 hours
- OAuth
- Works in Glama
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- usestring/string-ai-mcp
- GitHub Stars
- 7
- Server Listing
- String AI Web Access MCP Server
- ChatGPT
- –
- Claude
- –
TDQS
Scored across 4 tools
The four tools mostly have distinct purposes: search for queries, fetch for reading URLs, request for sending bodies, and sitemap for crawling. Fetch and request could be confused since both hit a URL, but the descriptions explicitly separate reading via GET from submitting via POST/PUT/PATCH.
All tool names use the same predictable `web_access_<action>` pattern: fetch, request, search, sitemap. The convention is consistent across the entire set.
Four tools is well-scoped for a web access server: query, read, submit, and crawl. Each tool earns its place without redundant surface area.
The set covers the core web-access lifecycle: search, fetch, non-GET requests, and asynchronous crawling. There is a minor gap around other HTTP methods such as DELETE, and no dedicated structured extraction tool beyond fetch formats, but core workflows are covered.
Available Tools
4 toolsweb_access_fetchFetch a web pageADestructiveInspect
Fetch a caller-specified HTTP(S) URL and get clean, LLM-ready Markdown back.
Primary use (the common case): pass only a url. The page is fetched with a normal GET and returned as Markdown — no other parameters are needed.
{ "url": "https://example.com/article" }Best for: any URL, especially sites that block automated traffic or render their content client-side (news, docs, blogs, web apps). Not for: searching the web when you don't have a URL — use web_access_search instead.
Optional parameters (omit unless you need them):
format—markdown(default),raw(the destination's verbatim body), orjson(a{ statusCode, headers, data }envelope with the destination's status and headers).executeJS— set true to render JavaScript for SPAs when the content comes back empty.actions— drive a real browser (click, scroll, type, wait) before capturing the page. See below.
To send a direct POST, PUT or PATCH (with a body), use web_access_request — this tool's direct HTTP path only issues GETs. Plenty of those calls are reads: a GraphQL query, a search backend that takes a body, a JSON API that refuses GET.
headers— forward custom request headers; not combinable withexecuteJSoractions, which run in a browser.countryCode— ISO 3166-1 alpha-2 (e.g. "US") to route through a proxy in that country.solveCaptcha— defaults true; set false to fail fast instead of spending effort solving a challenge.
Returns: Markdown by default; the verbatim body or a JSON envelope when format is set accordingly.
actions — driving the page instead of just loading it
An actions sequence runs in a real browser session and returns the page as it stands after the last step. Use it when the content you need does not exist in the document until something happens to the page: a click past a consent gate, a search form submitted, a "load more" button, a tab or accordion opened, or rows that only render once scrolled into view.
Actions can modify destination data or submit a form, so clients should treat any call to this tool as potentially destructive.
Escalate in this order — each step takes longer than the last, and steps 2 and 3 bill at the browser rate:
Plain
url— always try this first.executeJS: true— the page renders client-side but needs no interaction.actions— the content requires interaction. Takes tens of seconds and holds a browser session.
If the data is still absent after all three, it is likely never in the HTML at all — look for the JSON API the page itself calls and fetch that endpoint directly, which is faster and returns exact values.
Steps (max 50 per request; at most one screenshot):
{"type": "wait", "selector": ".price", "timeout": 20000}— wait until the selector appears, then continue immediately. Prefer this over a fixed pause.{"type": "wait", "milliseconds": 3000}— fixed pause. Max 30000ms, as istimeoutabove.{"type": "click", "selector": "#accept", "all": false}—all: trueclicks every match.{"type": "write", "text": "..."}— types into the focused element; click it first.{"type": "press", "key": "Enter"}{"type": "scroll", "direction": "down", "amount": 1000, "selector": "..."}—selectorscrolls that element instead of the page.{"type": "hover", "selector": "..."}{"type": "selectOption", "selector": "select#size", "value": "L"}—valuemay be an array.{"type": "navigate", "url": "https://..."}— go to another page mid-session, keeping cookies and state.{"type": "screenshot", "full_page": true, "quality": 80}
The session opens on url before your first step, so never begin with a navigate to that same URL.
Examples
Dismiss a cookie banner, then read the page:
{ "url": "https://example.com/pricing", "actions": [
{ "type": "click", "selector": "#accept-cookies" },
{ "type": "wait", "selector": "main .plan", "timeout": 15000 }
] }Run a search the site offers no URL for:
{ "url": "https://example.com", "actions": [
{ "type": "click", "selector": "input[name=q]" },
{ "type": "write", "text": "standing desk" },
{ "type": "press", "key": "Enter" },
{ "type": "wait", "selector": ".results .item", "timeout": 20000 }
] }Fill in rows that render only as they scroll into view:
{ "url": "https://example.com/listings", "actions": [
{ "type": "wait", "selector": ".card", "timeout": 20000 },
{ "type": "scroll", "direction": "down" },
{ "type": "wait", "milliseconds": 1500 },
{ "type": "scroll", "direction": "down" },
{ "type": "wait", "milliseconds": 1500 }
] }Returns with actions: a JSON object — data (the final page, Markdown by default), finalUrl, statusCode, and screenshot when the sequence took one. If a step fails, the call still succeeds and returns error plus failedActionIndex, a 0-based index into your actions array, with data holding the page as it stood at that point — read it to see what the page actually showed, then fix that step's selector.
Not combinable with headers or format: "raw"; a browser session is always a GET.
Requests must comply with destination policy, robots directives, rate limits, and access controls. Challenge handling is subject to the caller's String account and organization policy.
Inputs: url (required), format, actions, headers, +3 more. Returns: body, error, headers, finalUrl, +3 more
web_access_requestSend a web requestADestructiveInspect
Send a POST, PUT or PATCH request to any URL, through String's Web Access API. It works like web_access_fetch, but for calls that submit data rather than read a page — a JSON API that only accepts POST, a GraphQL endpoint, a search backend that takes a body.
Use web_access_fetch instead whenever you only need to read a page. This tool sends a body to the destination rather than reading it, so use it only for a request the user actually asked for.
Usage Example:
{
"url": "https://api.example.com/search",
"method": "POST",
"body": { "q": "widgets" }
}Returns: The destination's response, in the requested format.
Inputs: url (required), method (required), body, format, +3 more. Returns: body, error, headers, finalUrl, +3 more
web_access_searchSearch the webARead-onlyInspect
Search the public web for a caller-specified query and get ranked organic results back, plus whatever Google rendered around them: knowledge panel, AI overview, People also ask, local pack, videos, discussions. Google's images, videos, shopping, books, places and forums tabs are searched with searchType.
Primary use: pass a query string. There is no engine or domain-filter parameter; any other key is rejected before the call.
{ "query": "site:arxiv.org retrieval augmented generation" }Optional targeting fields: country — ISO 3166-1 alpha-2 code the search runs from, e.g. GB (default US); language — results language tag such as en or pt-br.
{ "query": "plumbers", "country": "GB", "language": "en" }To search from a place, send location, a place name such as London or Austin,Texas,United States (1 to 200 characters), or coordinates, { latitude, longitude, radius } with radius in meters (default 5000). The search is sent from that place's country; if both are sent, coordinates win. A name that cannot be placed fails, so send coordinates instead. On the results page the place biases results toward it. The effect is strongest for queries like plumbers near me, and it is not exact city targeting: a bare query such as coffee shops may still return results from a wider area.
{ "query": "plumbers near me", "location": "Austin,Texas,United States" }Optional request field: searchCount — how many organic results you want, an integer from 1 to 300 (above 300 is rejected). Google is paged, up to 36 pages, until that many are in hand; each page is billed as one search. Many queries run out before 300: Google often has 100-200 results for a query, and you get what it has, with paging.complete: true and paging.stoppedBy: "end_of_results". Omit it for one page, about 10 results, and the response then carries no paging. Not with format: "raw", which returns one page per call.
{ "query": "construction consulting firms Ohio", "searchCount": 30 }Optional Google field: searchType — the Google tab to search: "web" (the default, the ordinary results page), "images", "videos", "shopping", "books", "places" or "forums". There is no news tab. Each page fetched is billed as one search, as on the web.
videos,books,forumsanswerresults, paged like the web; each video carriesvideo(channel,platform,duration) and each bookbook(authors,published).imagesanswersimages, about 100 a page, each withtitle,url(the page it is on),source,imageUrl(the file),imageWidth,imageHeightandthumbnail. It has 3 pages;searchCountup to 300 collects across them, usually about 270 images.shoppinganswersproducts, the one page of about 55 product cards:title,productId,priceandoriginalPriceas shown,merchantandmoreMerchants,delivery,returns,rating,reviews. A card has nourl. Google does not page this tab, sopagemust be 1.placesanswersplaces, 20 businesses a page, paged like the web up to page 15.resultsis empty for images, shopping and places.dateRange,sortByandverbatimapply to web, videos and forums only;format: "raw"andaiOverviewto web only.
{ "query": "eames lounge chair", "searchType": "images", "searchCount": 150 }Optional Google filters: safeSearch — true removes explicit results; includeOmittedResults — true includes the results Google hides as very similar to ones shown; autocorrect — false searches the query exactly as typed instead of Google's correction; restrictCountry — a two-letter code — keeps only pages from that country (unlike country, which sets where the search runs from); verbatim — true matches the words exactly, without synonyms. None combines with aiMode.
{ "query": "climate policy", "restrictCountry": "FR", "safeSearch": true }Optional Google fields: page, dateRange and sortBy apply to Google results only; none of them combines with aiMode.
page— the results page to start from, an integer from 1 to 30 (default 1), where page N is the page Google shows as N. WithoutsearchCountthe response is that one page; with it,searchCountresults are collected starting from that page.pageandsearchCounttogether stay within the first 300 results: (page - 1) × 10 + (searchCount, or 10 without it) must be at most 300. A page past Google's last result returns no results withzeroResults: true. Pages hold 8-10 results, so separatepagecalls can repeat or skip a result; for one list without repeats, send one call withsearchCount.dateRange— limit results to a publication window: one of"hour","day","week","month"or"year"for the past hour through the past year, or{ "from": "2024-01-01", "to": "2024-06-30" }for a custom range of ISO dates (YYYY-MM-DD), inclusive. Either end is optional but at least one is required, andfrommust not be afterto.sortBy—"relevance"(the default) or"date"for the newest results first.
{ "query": "heat pump grants", "page": 2, "dateRange": "month", "sortBy": "date" }Optional Google field: format — "structured" (the default, recommended) for the parsed results above as JSON, or "raw" for the Google results page as HTML, one page per call. The response is then html, htmlBytes and htmlTruncated in place of results and the surfaces. This tool sends at most 60,000 bytes of markup per call and sets htmlTruncated: true when it cuts the page; for the whole page, call the HTTP API's POST /v1/search with format: "raw". Raw supports page only, not searchCount: a raw call with searchCount is rejected (the API answers 400), so ask for page N with page and send one call per page, each billed as one search. dateRange and sortBy work with raw. Not combinable with aiMode.
{ "query": "heat pump grants", "format": "raw" }Optional request field: aiMode: true — ask Google AI Mode instead of the results page. The response is aiMode, one generated answer with the pages it cites and any products, places and videos it shows, and results is empty. Billed as one search. It cannot be combined with searchCount. If an AI Mode answer isn't available for the query, the call fails instead of returning a results page; retry, or search without it.
{ "query": "how does a heat pump work", "aiMode": true }With aiMode, location or coordinates sets the place the answer is given for; the answer stays in language. Without either, a question that depends on where you are, such as today's weather, may be answered without a location.
{ "query": "best bakeries nearby", "aiMode": true, "coordinates": { "latitude": 48.8566, "longitude": 2.3522 } }Optional request field: aiOverview: true — fill the AI Overview Google streams in after the results page loads. It makes a second, sequential fetch and adds latency: about 64% of results pages carry a streamed overview, and filling it adds about 2.8 s at p50 and 5.6 s at p90. A request with aiOverview: true costs 2x a normal search. Off by default: without it, an overview already present in the page is still returned, and a streamed one comes back as declined: true. Not combinable with aiMode.
{ "query": "best cushioned marathon shoes", "aiOverview": true }Best for: a request that names no URL, or one that needs sources found before anything is read. Not for: a URL you already have — use web_access_fetch instead.
Query operators: quoted phrases and site: pass through to the search engine, so site:example.com pricing keeps results on that host. Other operators are untested — do not rely on them.
Returns: results, the ranked web documents, each with position (its place in this response, from 1), rank (its absolute Google rank, so page 3 starts at 21; Google only), title, url (the link to fetch; absent when Google hid the destination, and the result is still returned), snippet, displayUrl (Google's displayed URL line, empty when Google shows none, as on Reddit and YouTube results), displayText (the source line Google shows under the title, verbatim: a URL, engagement counts such as 20+ comments · 3 months ago, or other text), source when Google names the site (such as Reddit · r/buildapc), and timestamp when the engine dates it; and zeroResults, true when the engine itself reported no match (broaden the query; retrying will not help). Every other field is a surface Google rendered around the documents, present only when the page carried it, never merged into results, and only Google returns them:
entity— the knowledge panel for the one business or person the query named:title,subtitle,descriptionwith itsdescriptionSource,rating,reviews,website, labelledattributes(address, phone, hours…), socialprofiles, andunreadmodule ids the read skipped. Often the whole answer for a query naming a single business, withresultsempty.places— local-pack business listings:name,category,rating,reviews,address,phone,hours,url,mapsUrl. Also often answers a business query withresultsempty, so readentityandplacesbefore treating an emptyresultsas no answer. WithsearchType: "places"it is the whole answer.products— only withsearchType: "shopping", the product cards described above.overviews— Google's AI overviews. The first entry with notopicis the query's own summary; entries with atopicandquestionare the "Things to know" tabs; an entry withdeclined: trueis a frame Google rendered and did not fill, which includes an overview Google streams in whenaiOverviewwas not set. Each carriestext(paragraphs and-list items on their own lines) andsources, the cited pages as{ title, url }— fetch those to verify a claim.peopleAlsoAsk—{ question }entries; answers are not on the page.relatedSearches— query strings Google suggests.answers— one single-purpose widget underlocalTime,currency,unitConversion,weather,translation,sportsorflights.spelling—{ kind, query, asked }:substitutedmeans the results are for the correctedquery,suggestedmeans they are for the query as typed.ads(sponsored, withadvertiser),videosandshortVideos(platform,channel,date,duration),discussions(site,forum,comments,age,excerpt),images(source; withsearchType: "images"the whole answer, with the image file too),sitelinks(resultPositionof the result they sit under). Every entry haspositionandtitle, andurlwhen its destination is known.aiMode— only withaiMode: true: Google's AI Mode answer.textis plain text (one block per line, list items as-, table rows with cells joined by|);markdownis the same answer as Markdown, with headings, lists, tables and code;blocksis its structure in reading order, each{ type }ofparagraph,heading(text,level),list(ordered,items),table(header,rows, one cell per column) orcode(text,language).sourcesare the cited pages as{ title, url, snippet, source }:snippetis the passage quoted,sourcethe site's name, andurlis absent when a citation could not be resolved. When the answer shows them,products(title,priceandoldPriceas displayed,merchantandmoreSellers,rating,reviews,thumbnail,productId,url),places(name,category,rating,reviews,priceLevel,status,address,description,url) andvideos(title,url,channel,duration,thumbnail). Every field buttextandsourcesis absent when empty. Fetch the sources to verify a claim.paging—{ pages, complete, stoppedBy }, only whensearchCountwas sent.pagesis how many results pages answered, each billed as one search.stoppedByis why paging stopped:search_count(the count was reached),end_of_results(Google had no more),page_cap(the 36-page depth limit; Google may have more),page_failed(a later page could not be fetched) ordeadline(the time budget ran out).completeis false only forpage_failedanddeadline, andresultsthen holds what was collected. Surfaces describe the first page only; positions run on across pages.
A snippet is not the page, and an overview is not a source. To read a result, call web_access_fetch on its url before answering from it.
Requests must comply with destination policy, rate limits, and access controls.
Inputs: query (required), page, aiMode, format, +14 more. Returns: ads, html, aiMode, entity, +17 more
web_access_sitemapMap a site's URLsADestructiveInspect
Manage an asynchronous crawl of authorized public pages on one website. Starting from one URL, the crawler follows same-domain links breadth-first and can also seed from the site's /sitemap.xml. Requests must comply with destination policy, robots directives, rate limits, and access controls.
Use this tool to discover pages for site audits, authorized retrieval worklists, or coverage checks before fetching individual pages. Not for: reading one page's content (use web_access_fetch) or open-ended web queries (use web_access_search).
This single tool drives the whole job lifecycle through action:
1. submit — quote a crawl (nothing is crawled or billed yet). Requires url. Optional: maxPages (1–10000, default 10), maxDepth (1–100, default 2), pathPrefix (only crawl URLs whose path starts with this, e.g. "/docs"), budgetUsd (spend ceiling; the crawl stops with status token_cap_exceeded if it would exceed it), useSitemap (also seed the site's root /sitemap.xml — one extra billed page, but finds pages links miss). A maxPages or maxDepth outside its range, 0 included, is rejected rather than replaced by the default — omit the field to get the default. Returns jobId, estimatedPages, and estimatedCostUsd with status awaiting_approval.
{ "action": "submit", "url": "https://example.com", "maxPages": 200, "maxDepth": 3 }2. approve — start the quoted crawl (requires jobId). This is the billing-consent step: pages are billed as they are fetched, capped by the quote/budget. Before approving a non-trivial estimatedCostUsd, confirm the spend with your user. Fails with status 402 if the account balance cannot cover the quote; a 409 partial_state error means an earlier approve was interrupted — just call approve again.
3. status — poll progress (requires jobId). Statuses: awaiting_approval → running → terminal completed | failed | canceled | token_cap_exceeded (budget hit before maxPages; collected results are still readable). While running it returns pending and processed counts; a partial_state status means an interrupted approve — call approve again to repair it. Status never includes the URL list — page that with results. Poll every few seconds for small crawls; give hundreds-of-pages crawls tens of seconds between polls.
4. results — page through discovered URLs (requires jobId). Optional limit (1–5000, default 1000) and offset (≥ 0); out-of-range values are rejected. total tells you when to stop paging. Each entry has url, statusCode (0 = discovered but not fetched), depth, parentUrl, isSitemap, sourceType, and an error when that page failed. discoveredUrls (links found on the page) is only present for ~1h after completion; afterwards results come from durable storage which omits it — everything else stays available.
5. cancel — stop a running or pending job (requires jobId). Already-terminal jobs return a 409 error. Pages already fetched stay billed and readable via results.
6. list — recent crawl jobs for the account. Optional limit (1–100, default 20) and offset (≥ 0); out-of-range values are rejected. Use it to find a jobId you lost or check for an equivalent recent crawl before paying for a new one.
Typical workflow: submit → check estimatedCostUsd → approve → poll status until terminal → results (paged). A 404 on any jobId action means the job doesn't exist or belongs to another account; a 403 on submit means the target domain is blocked for this account (contact support@usestring.ai).
Returns: the JSON envelope for the chosen action (quote, status, URL page, job list) alongside a one-line summary.
Inputs: action (required), url, jobId, limit, +6 more. Returns: jobs, urls, jobId, total, +8 more
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
Related MCP Connectors
Web search, URL content extraction to Markdown, site mapping, and recursive web crawler.
Fetch pages as markdown, search web and news, extract structured data. For AI agents.
Fetch any URL and get clean Markdown. Web scraping for AI agents.
Read any web page as clean Markdown for AI agents: fetch, search, metadata, links. SSRF-safe.
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables any MCP-compatible AI agent to search the live web and fetch pages as clean Markdown, including batch fetching with rate limiting, retries, and context-safe truncation.3MIT
- AlicenseNot gradedqualityAmaintenanceFetches webpages and converts them into clean, token-efficient Markdown, optionally crawling multiple linked pages while respecting robots.txt and caching results for AI agents and LLM pipelines.MIT
- AlicenseAqualityCmaintenanceWeb search and any page as LLM-ready Markdown for AI agents, pruned to the passages relevant to the query, plus research, crawl and site maps. Free keyless tier.11152 npm2MIT
- AlicenseAqualityDmaintenanceEnables AI agents to fetch any web page as clean markdown or screenshot it, turning URLs into LLM-ready context.24 npmMIT
Glama MCP Gateway
Add one secure layer between your agents and this server.