Razi Web Tools
by razikallayi · remote · no sign-in to list tools · v1.0.0 · published by GitHub user razikallayi
Web and URL utilities over MCP: shorten URLs, screenshot pages, read page metadata, encode URLs.
6 tools: 1 do something that can't be undone, 3 change things and 2 only read.
Scanned Oct 21, 2026
- Deletes or cancels0Claude Code: deny
- Can't be undone1Claude Code: ask: see these tools
- Changes things3Claude Code: ask: see these tools
- Only reads2Claude Code: allow: see these tools
2 checks matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.
claude mcp add --transport http razi-web https://www.razi.pro/api/mcp/webFindings
Matches of fixed checks, with the text they matched.
- Infoscreenshot_url
The description mentions "credentials".
What this check looks forMatched text
description: "...s in a fresh browser with no cookies or credentials, so anything behind a login is unreacha..."
- Infofetch_site_logo
The description is 2,025 characters long, over the 2,000 this check looks for.
What this check looks forMatched text
description ends: "...or 24 hours and replayed with cached: true; 20 calls per minute per IP, then 429."
Tools
Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.
6 tools
Can't be undone 1Claude Code: ask
screenshot_urlCapture a screenshot of any public web page, rendered in a real headless browser so JavaScript, web fonts and lazy-loaded images all appear.1 finding
Why it is in this group
- The name "screenshot_url" says "screenshot": a word for reading.
- The description's first verb is "capture": a word that usually means money moves, which cannot be taken back.
Findings
- Info
The description mentions "credentials".
What this check looks forMatched text
description: "...s in a fresh browser with no cookies or credentials, so anything behind a login is unreacha..."
Description, as the server wrote it Capture a screenshot of any public web page, rendered in a real headless browser so JavaScript, web fonts and lazy-loaded images all appear. Returns JSON with a hosted image URL — not image bytes: { url, screenshotUrl (the same value under the older key), width, height, format, bytes, cached, source }. When source is "vps" the image is on razi.pro's CDN and every field is populated, except that height is null for a fullPage capture. If source is "thumbio" the renderer was unavailable and a third-party fallback produced the image: the URL points at image.thum.io rather than razi.pro, only width accompanies it (height, format and bytes are absent), and the fullPage, format, darkMode and delayMs options were ignored. Public pages only: every capture runs in a fresh browser with no cookies or credentials, so anything behind a login is unreachable, and a URL that is not http(s) or that resolves to a loopback, private or link-local address is refused with 400. Identical requests are cached for 7 days and return the same image (cached: true), so this cannot be used to poll a page for changes. Out-of-range numeric options are clamped to their stated range rather than rejected. Other failures: 429 over either rate limit, 403 when screenshots are switched off platform-wide, 502 when the render fails and no fallback is available. This is the most expensive call on the platform: it holds a whole browser worker for up to 50 seconds. Limited to 10 captures per minute and 100 per day per IP.
Changes things 3Claude Code: ask
decode_urlReverse percent-encoding with decodeURIComponent, turning %20-style escapes back into the characters they stand for.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Reverse percent-encoding with decodeURIComponent, turning %20-style escapes back into the characters they stand for. Returns JSON { decoded }. A malformed or truncated escape sequence is rejected with an error rather than passed through. Note that '+' is left as a literal plus, not converted to a space. It understands percent-escapes and nothing else: Base64 text and JWTs pass through unchanged or fail, rather than being decoded. It is the exact inverse of encode_url.
encode_urlPercent-encode a string with encodeURIComponent so reserved characters survive transport inside a URL.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Percent-encode a string with encodeURIComponent so reserved characters survive transport inside a URL. Returns JSON { encoded }. It escapes the structural characters too — : / ? # & = all become %XX — so it is for a single query-string value or path segment, NOT for a whole address you still want to be clickable. This is escaping for URLs only. It is the wrong transform for making binary-unsafe content fit in JSON, an HTTP header or a data URI, which call for Base64 rather than percent-encoding. Reverse it with decode_url.
shorten_urlCreate a permanent razi.pro short link that redirects to a long URL.No findings
Why it is in this group
- The description's first verb is "create": a word for a change.
Description, as the server wrote it Create a permanent razi.pro short link that redirects to a long URL. Returns JSON { code, shortUrl } and nothing else. Visits through the link are counted, but no tool here reads that count back, and the link cannot be edited, retargeted or deleted through this API. It never expires. The destination is stored, never fetched or checked for reachability, so a dead or mistyped URL still yields a working short link. Only http and https targets are accepted. This shortens an existing address; it does not host anything, so a file needs a public URL of its own before there is something to shorten. No sign-in is required; an anonymous call creates the link unowned, so it will not appear in any account's list. 30 links per hour per IP, then 429.
Only reads 2Claude Code: allow
fetch_page_metadataRead a web page's metadata without downloading any images.No findings
Why it is in this group
- The name "fetch_page_metadata" says "fetch": a word for reading.
Description, as the server wrote it Read a web page's metadata without downloading any images. Returns JSON { url, finalUrl, title, description, siteName, canonical, lang, themeColor, author, generator, feeds, openGraph, twitter, icons, cached }, where `feeds` is an array of RSS/Atom URLs, `openGraph` and `twitter` are the complete tag sets as string maps, and any tag the page does not declare is simply omitted. `icons` is always an empty array here because icon resolution is switched off — call fetch_site_logo when the caller wants a logo, favicon or icon. `finalUrl` is the address after redirects (up to 3 hops are followed), which is how you resolve where a domain actually points. This is the fast, cheap counterpart to fetch_site_logo: one page fetch and no image work. It reads the served HTML only — it runs no JavaScript, so a client-rendered page may expose little, and it does not capture how the page looks (use screenshot_url for that). The crawler identifies itself as RaziMetadataBot, and HTTP status is not checked, so a 404 or bot-challenge page that serves HTML is parsed as though it were the page you asked for. Errors: 400 for a URL that is refused as unsafe, redirects too many times, does not return HTML, or exceeds the 5MB page cap; 504 if the page does not answer within 10 seconds; 502 otherwise. Results are cached for 24 hours and replayed with cached: true; 20 calls per minute per IP, then 429.
fetch_site_logoGet a company's logo from its website URL.1 finding
Why it is in this group
- The name "fetch_site_logo" says "fetch": a word for reading.
Findings
- Info
The description is 2,025 characters long, over the 2,000 this check looks for.
What this check looks forMatched text
description ends: "...or 24 hours and replayed with cached: true; 20 calls per minute per IP, then 429."
Description, as the server wrote it Get a company's logo from its website URL. Reads the web app manifest, apple-touch-icons, declared favicons, OpenGraph/Twitter images and /favicon.ico, then downloads at most the first 10 candidates and measures their real dimensions — declared `sizes` attributes are frequently wrong, so ranking uses the measurement rather than the claim. Returns JSON { logo, icons, cached } plus the same page-metadata fields as fetch_page_metadata (url, finalUrl, title, description, siteName, canonical, lang, themeColor, author, generator, feeds, openGraph, twitter), so there is no need to also call it. Use that tool instead if you do NOT need the logo: it skips the image downloads entirely and is much faster. `logo` is the best candidate and is absent when nothing usable was found; `icons` lists all candidates, best first, with real icon assets deliberately outranking social share images, which are usually a wide marketing banner rather than a logo. If the site declares nothing fetchable, a Google favicon-proxy candidate (source "google-proxy") is added as a last resort. Each candidate is { url, source, declaredSizes?, width, height, format, bytes, rehostedUrl? }. Candidates the site declares but that cannot be fetched are still returned last, carrying an `error` field — that is what makes this useful for auditing your own site's icons. SVG logos carry no width/height because they are not rasterised, and a .ico often comes back unmeasured for the same reason. The served HTML is read with no JavaScript executed, and the crawler identifies itself as RaziMetadataBot, so a site that challenges unknown bots yields the challenge page's icons. HTTP status is not checked: a 404 page that serves HTML is parsed as though it were the page you asked for. Errors: 400 for a URL that is refused as unsafe, does not return HTML, or exceeds the 5MB page cap; 504 if the page does not answer within 10 seconds; 502 otherwise. Results are cached for 24 hours and replayed with cached: true; 20 calls per minute per IP, then 429.
This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.
Install
Pinned to version 1.0.0. Values in angle brackets are yours to fill in.
claude mcp add --transport http razi-web https://www.razi.pro/api/mcp/webRun in a terminal.
Claude Code permissions
Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.
{
"permissions": {
"allow": [
"mcp__razi-web__fetch_site_logo",
"mcp__razi-web__fetch_page_metadata"
],
"ask": [
"mcp__razi-web__shorten_url",
"mcp__razi-web__screenshot_url",
"mcp__razi-web__encode_url",
"mcp__razi-web__decode_url"
],
"deny": []
}
}Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as razi-web. Review it before you use it.
