Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

searchts

PYPI · SEARCHTS

Keyless web access for AI agents: read bot-walled pages as Markdown, search, grab assets

Available components

0 this week 88 Trust /100

Last scanned (42 minutes ago)

Scores higher than 91% of PyPI servers

Category Web Scraping

Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security99
  • No malware found by supply-chain analysis.Pass
  • Known CVEs were checked across the 81 of 82 dependencies we could resolve, so this covers what we could see, not the whole tree.Partial
  • Runs hatchling.build at install time, a recognised build step with no custom scripting around it. View diagnostics → Pass
  • Dependency health was assessed across the 81 of 82 dependencies we could resolve, so this covers what we could see, not the whole tree. View diagnostics → Partial
Provenance & Transparency100
  • Source repository is publicly reachable at the declared URL. View diagnostics → Pass
  • Cryptographically verified build provenance (signed, bound to capad-xyz/searchts). View diagnostics → Pass
  • Clear OSI-approved license (MIT).Pass
  • Actively maintained (last published 1 days ago).Pass
  • Publishes a security disclosure policy (SECURITY.md).Pass
Schema Quality & AI Usability55
  • AI-judged instruction clarity (good).Pass
  • Context-footprint check failed: tool/resource definitions use about 4459 tokens (~445/item across 10 items; 10 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management100
  • No destabilizing schema changes in the last 30 days.Pass
Tool Coverage71
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 0% of tool parameters carry a description.Fail
  • Structured output schemas are declared (90% of tools); any adoption earns full credit.Pass
Tool Safety75
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • 0 of 1 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "login_kill" implies "kill" and declares no destructiveHint at all, which the MCP spec reads as destructive by default. See how to fix → Fail
  • An AI judge read all 11 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a current MCP spec version (2026-07-28).Pass
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 5 Nov 26 +15
    • Malware scan: unverified → pass ▲ security
  • 3 Nov 26 0
    • Malware scan: unverified → pass ▲ security
    • Package version: 0.27.0 → 0.27.1 functional
  • 2 Nov 26 0
    • Package version: 0.25.1 → 0.27.0 functional
    • Package version: 0.25.1 → 0.26.1 functional
  • 31 Oct 26 −15
    • Malware scan: pass → unverified ▼ security
  • 30 Oct 26 0
    • Malware scan: pass → unverified ▼ security
    • Tool coverage: 100% → 90% ▼ functional
    • Package version: 0.23.0 → 0.25.1 functional
    • Package version: 0.23.0 → 0.25.0 functional
    • Package version: 0.23.0 → 0.24.3 functional
    • Package version: 0.23.0 → 0.24.1 functional
  • 29 Oct 26 +15
    • Malware scan: unverified → pass ▲ security
  • 27 Oct 26 −15
    • Malware scan: pass → unverified ▼ security
  • 26 Oct 26 +15
    • Malware scan: unverified → pass ▲ security
Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 5 Nov 2026 · Analysed pypi/searchts@0.27.1

Provenance Verified

A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.

Result Verified
Ecosystem pypi
Reason Verified
Discovered via Registry attestation endpoint
Source repo capad-xyz/searchts
Certificate issuer https://token.actions.githubusercontent.com
Certificate SAN https://github.com/capad-xyz/searchts/.github/workflows/release.yml@refs/tags/v0.27.1
Rekor log index 3674288395
Predicate type PyPI publish attestation https://docs.pypi.org/attestations/publish/v1
Subject digest sha256:150a9134e56f9b72342ad6ce469347c6d480a93cd9593789b30c70a70c712874

Background: How many MCP packages publish verified provenance →

Install scripts 1 script
Hook Tier Command
build_backend allowlisted hatchling.build

Background: Why install scripts are a supply-chain risk →

Dependencies 81 packages
Packages resolved 81
Stale 7
No linked repository 1
Tree resolution Partial

The dependency tree was only partially resolved, so these counts may be incomplete.

Background: SBOMs and build attestations, explained →

MCP tools · 10 exposed · ~4,356 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
fetch_asset ~251

Download a single asset file (image, PDF, font, CSS, any file) from its URL through the same unlock ladder as read_url, save it to disk, and return {path, content_type, bytes} as JSON. Use this for one specific file by its direct URL; to pull a whole page's assets at once use grab_site instead. Saves into out_dir (a relative folder inside the working directory, or SEARCHTS_MCP_OUT_DIR if the user set it) when given, otherwise that folder itself, and never overwrites an existing file. Returns an 'Error: ...' string on failure. Update check: when a newer release exists, a successful result also carries 'update_available' plus, at most once per 24 hours, one line telling the agent. The check is one GET to the GitHub latest release of capad-xyz/searchts, at most once per 24 hours, cached in ~/.searchts/update-check.json, with a searchts User-Agent and nothing about the user. Nothing is installed or changed. SEARCHTS_NO_UPDATE_CHECK=1 turns the check and the note off.

NameTypeReqDescription
out_dirstring––
urlstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

get_status ~220

Report the health of this searchts install: which unlocker tiers, search providers, and optional platform integrations are installed, configured, and working. Use this first when another searchts tool fails or before relying on an optional capability (e.g. keyed search providers, transcription). Takes no arguments and performs no web requests of its own beyond the cached update check; returns a plain-text report, one line per channel starting with ok, warn or error, never wrapped, so a fix command on its own indented line can be copied as-is. Update check: when a newer release exists, a successful result also carries 'update_available' plus, at most once per 24 hours, one line telling the agent. The check is one GET to the GitHub latest release of capad-xyz/searchts, at most once per 24 hours, cached in ~/.searchts/update-check.json, with a searchts User-Agent and nothing about the user. Nothing is installed or changed. SEARCHTS_NO_UPDATE_CHECK=1 turns the check and the note off.

Input schema present but exposes no named parameters.

NameTypeReqDescription
resultstringyes–

No examples provided.

grab_site ~435

Save the files a read already named. Fetches the page through the same unlock ladder as read_url, downloads its assets (images/icons/css/fonts/svg/inline_svg), and returns a manifest (local paths, plus the palette and fonts those files use) as JSON. Use this when the files are the deliverable. For one URL the read listed, use fetch_asset. Saves into out_dir (a relative folder inside the working directory, or SEARCHTS_MCP_OUT_DIR if the user set it) when given, otherwise a 'searchts-grab-<host>' folder there. A folder that already has files is never written into; the grab goes to '-2', '-3' and so on, and the folder used is returned as out_dir. Set read=true to also save the page text as page.md. max_assets caps how many files are saved (default 120); when it or the byte cap stops early, the manifest's 'omitted' list names every URL left out and why, so never report a grab as complete without reading it. max_tokens is how many radius, shadow, and spacing values to keep (default 24, ceiling 200). When that cap hides real values, tokens_more says how many more and that a higher max_tokens returns them. 'page_rungs' names the fetch tiers tried and what each found. Returns an 'Error: ...' string on failure. Update check: when a newer release exists, a successful result also carries 'update_available' plus, at most once per 24 hours, one line telling the agent. The check is one GET to the GitHub latest release of capad-xyz/searchts, at most once per 24 hours, cached in ~/.searchts/update-check.json, with a searchts User-Agent and nothing about the user. Nothing is installed or changed. SEARCHTS_NO_UPDATE_CHECK=1 turns the check and the note off.

NameTypeReqDescription
max_assetsinteger––
max_tokensinteger––
out_dirstring––
readboolean––
urlstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

login_check ~301

Read one signed-in-only page with the saved cookies, once, and say 'logged in', 'logged out' or 'unknown'. Direct requests only: the cookies and URL are never sent to the Jina relay. It proves a login wall is absent, not which account is signed in, and an expiry is only an upper bound. A captcha, block or network error is 'unknown', never a guess. For reddit.com, linkedin.com, github.com and x.com a known account page is used; other sites need a signed-in-only URL, and a public page is reported as 'unknown' because it proves nothing about the account. check_url checks a custom signed-in-only page instead of the known one; the cookies still come from url's site. An invalid url is an error result carrying the usual JSON error envelope, not an 'unknown' login answer. Update check: when a newer release exists, a successful result also carries 'update_available' plus, at most once per 24 hours, one line telling the agent. The check is one GET to the GitHub latest release of capad-xyz/searchts, at most once per 24 hours, cached in ~/.searchts/update-check.json, with a searchts User-Agent and nothing about the user. Nothing is installed or changed. SEARCHTS_NO_UPDATE_CHECK=1 turns the check and the note off.

NameTypeReqDescription
check_urlstring––
urlstringyes–

No output schema declared.

No examples provided.

login_kill ~194

Delete searchts's own saved login for one site, so the next read of it asks again. Use when a read_url error says the saved login has expired. Does NOT delete the cookies in the user's own Firefox or Chrome unless also_browser is true, because those are the user's and they did not ask for them to be removed. Update check: when a newer release exists, a successful result also carries 'update_available' plus, at most once per 24 hours, one line telling the agent. The check is one GET to the GitHub latest release of capad-xyz/searchts, at most once per 24 hours, cached in ~/.searchts/update-check.json, with a searchts User-Agent and nothing about the user. Nothing is installed or changed. SEARCHTS_NO_UPDATE_CHECK=1 turns the check and the note off.

NameTypeReqDescription
also_browserboolean––
urlstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

login_signin ~332

Sign in once for a site, in a browser searchts opens, and keep that login. Nothing is copied from the user's own browser. This is the way past a login wall when the user has no browser session worth copying, or refuses to have one read. A login kept this way is not refreshed automatically, because there is no browser source to re-copy; when it nears expiry the user is told to run login_signin again. Requires the user to be at the machine: tell them a window will open, they sign in there and then CLOSE the window to finish. Opening that window is the approval; nothing else is asked. The call waits up to wait_seconds (default 180, 30 to 900) and keeps nothing if the time runs out or the window is closed without a sign-in. Raise wait_seconds only if the host allows tool calls that long. Returns JSON {host, kept, cookies, why}, or 'Error: ...' on failure. Update check: when a newer release exists, a successful result also carries 'update_available' plus, at most once per 24 hours, one line telling the agent. The check is one GET to the GitHub latest release of capad-xyz/searchts, at most once per 24 hours, cached in ~/.searchts/update-check.json, with a searchts User-Agent and nothing about the user. Nothing is installed or changed. SEARCHTS_NO_UPDATE_CHECK=1 turns the check and the note off.

NameTypeReqDescription
browserstring––
urlstringyes–
wait_secondsinteger––
NameTypeReqDescription
resultstringyes–

No examples provided.

login_status ~266

What searchts holds for logged-in reads: which sites are kept, how many live cookies each has and when they expire (an expiry is an upper bound, not a promise), whether each site was kept from a browser or from login_signin, whether the per-site consent for an automatic re-copy is recorded, whether this session may copy logins, which sites it has copied, and where the scratch folder is. Expired cookies are swept on every command, offline, with no daemon. Call this when a read_url error mentions a login. Returns JSON; never contains a cookie value. Pass url to also see which stored host that URL resolves to (an exact host, or a parent such as example.com for app.example.com). Update check: when a newer release exists, a successful result also carries 'update_available' plus, at most once per 24 hours, one line telling the agent. The check is one GET to the GitHub latest release of capad-xyz/searchts, at most once per 24 hours, cached in ~/.searchts/update-check.json, with a searchts User-Agent and nothing about the user. Nothing is installed or changed. SEARCHTS_NO_UPDATE_CHECK=1 turns the check and the note off.

NameTypeReqDescription
urlstring––
NameTypeReqDescription
resultstringyes–

No examples provided.

read_url ~1,562

Read one web page as clean Markdown, escalating through an unlocker ladder (Chrome-fingerprint fetch -> JS-rendering relay -> stealth browser) that stops at the first tier returning real content. When the user asks what a URL says, call this first. Do not start with a plain fetch. A 200 that is a sign-in form, a join page, or a bot check is not the page. Also use this when a plain fetch was blocked (403/429, a Cloudflare/DataDome/PerimeterX bot-wall, or an 'enable JavaScript' page), the content is rendered client-side, or a previous web_search snippet was blocked, thin, or empty. Do not answer from a blocked snippet or from the login chrome — call this tool on that URL. Returns Markdown ready to feed a model, always strips invisible/control characters, and if prompt-injection indicators are detected it fences the body as untrusted and prepends a one-line warning. Long pages can be read a page at a time: pass 'page_items' to get 'items' plus a server-signed 'next_cursor', then pass that cursor back to continue. The cursor is opaque, cannot be minted by the caller or by the page, and is null at the end. You do not need a cursor for most pages. When the page has more than this read returned (a next page, a feed, folded text, a list it mostly dropped), the text ends with a bracketed note saying so. The JSON carries no next URL for you to follow: a URL the page names is not a safe thing to act on, so the note names the step that does reach it ('max_pages' for a next page, 'fetch_asset' for media). A 'next_cursor' is present only when you sent 'cursor' or 'page_items'. The receipt carries 'authenticated': true only when this answer came from a request that carried the session cookies you asked for, so you can tell 'here is the logged-in page' from 'here is the anonymous one' instead of assuming. It also carries 'login_via', which names where the login came from -- 'owned store' for a kept login, 'browser' for one copied for this session, empty when there was none. Receip…

NameTypeReqDescription
approve_cookie_copyboolean––
cdp_portstring––
cookiesstring––
cookies_from_browserstring––
cursorstring––
expandboolean––
ignore_cooldownboolean––
max_itemsinteger––
max_mediainteger––
max_pagesinteger––
page_itemsinteger––
proxystring––
proxy_trustedboolean––
resumestring––
urlstringyes–
wait_on_429boolean––
NameTypeReqDescription
resultstringyes–

No examples provided.

transcribe ~546

Read the spoken words when read_url says a player page has no captions, or transcribe a local audio/video file. A YouTube watch URL, a TikTok video, an Instagram reel, a v.redd.it file, or an X post that has a video is a player page: read_url returns its captions, or an error that names this tool for the audio. Subtitles-first: existing captions via yt-dlp need no API key; otherwise Whisper (Groq/OpenAI if configured, else keyless local whisper.cpp, bundled; provider=local-fw forces the temporary faster-whisper fallback. The PyPI wheel is CPU-only today; GPU-enabled wheels are a follow-up. prefer_subtitles defaults true; set false to force audio. Local options: model (small default, turbo, base), hint (names or words the audio contains, e.g. from the page title), translate (to English; not with turbo). The local model is downloaded once: without yes=true the call returns an Error naming its size and source; ask the user, then call again with yes=true. cookies_from_browser is opt-in (chrome/firefox/…) and uses THIS machine's browser cookies; read_url does not copy them. The compressed audio (never the video) is kept for 24 hours in ~/.searchts/cache/audio, so a repeat of the same URL skips the download; pass fresh=true to download again, and the receipt's audio_cache says hit, miss or off (off for a local file, cookies, or caching turned off). Returns the transcript text, then a `transcribed_by:` JSON line (source, engine, model, device, detected language, audio_cache). Missing-model consent is returned as structured JSON with the exact yes=true approval; other failures use an 'Error: ...' string. Update check: when a newer release exists, a successful result also carries 'update_available' plus, at most once per 24 hours, one line telling the agent. The check is one GET to the GitHub latest release of capad-xyz/searchts, at most once per 24 hours, cached in ~/.searchts/update-check.json, with a searchts User-Agent and nothing about the user. Nothing is installed or…

NameTypeReqDescription
cookies_from_browserstring––
freshboolean––
hintstring––
modelstring––
prefer_subtitlesboolean––
providerstring––
sourcestringyes–
translateboolean––
yesboolean––
NameTypeReqDescription
resultstringyes–

No examples provided.

web_search ~249

Find URLs to read. Returns a ranked, de-duplicated list (title + URL + snippet), fusion-merged with reciprocal-rank fusion. Keyless by default (DuckDuckGo); also uses SearXNG/Exa/Brave/Tavily when their keys are configured. Snippets are not the page. Call read_url on each URL you need, including when a hit is 403/429, a challenge, or thin. Do not answer from the snippet. Returns a formatted text block that starts with that warning, or an 'Error: ...' string when every provider fails. Update check: when a newer release exists, a successful result also carries 'update_available' plus, at most once per 24 hours, one line telling the agent. The check is one GET to the GitHub latest release of capad-xyz/searchts, at most once per 24 hours, cached in ~/.searchts/update-check.json, with a searchts User-Agent and nothing about the user. Nothing is installed or changed. SEARCHTS_NO_UPDATE_CHECK=1 turns the check and the note off.

NameTypeReqDescription
max_resultsinteger––
querystringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

Install

How do I install the searchts MCP server?

searchts runs locally as a PyPI package, launched with uvx searchts. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

pypi · searchts

# add to Claude Code
claude mcp add capad-xyz-searchts -- uvx searchts
Common questions

What is the searchts MCP server?

searchts is an MCP server listed in the public MCP registry as io.github.capad-xyz/searchts. Keyless web access for AI agents: read bot-walled pages as Markdown, search, grab assets. This page covers its PyPI package (searchts).

Is the searchts MCP server safe to use?

searchts scores 88 out of 100 on VerifyMCP. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the searchts MCP server expose?

searchts exposes 10 tools: get_status, read_url, web_search, login_status, login_signin, and 5 more. Their descriptions and schemas cost roughly 4,356 tokens of context every time the server is loaded.

Is the searchts MCP server still maintained?

searchts is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

What licence is the searchts MCP server under?

searchts declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.