web-basics-mcp
This server provides web search and URL fetching tools.
Use
web_searchto search the web, with optional result limit.Use
fetch_urlto retrieve content from a URL, returning clean Markdown for HTML and Reddit, selectable text for PDFs, direct content for text/Markdown/JSON/XML, or native MCP image content.fetch_urlsupports reading long text in bounded chunks viastart_indexandmax_length.Both tools include caching for faster repeated requests.
It does not provide browser automation, JavaScript rendering, crawling, authentication, cookies, proxy/VPN routing, or answer synthesis.
Integrates with SearXNG to perform web searches, returning results (title, link, snippet) from a local or remote SearXNG instance.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@web-basics-mcpsearch for MCP server best practices"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
web-basics
A local MCP server for resilient web search and safe URL fetching. It runs over stdio, supports configured and keyless search providers, and leaves answer synthesis to the client.
Requirements
Node.js 20.18.1 or newer
A SearXNG instance or Brave Search API key is optional; keyless search can be enabled explicitly
fetch_url works without a configured search provider.
Related MCP server: Basic MCP Tools
Add To Codex
For automatic fallback with no required credentials:
codex mcp add web-basics \
--env SEARCH_PROVIDER=auto \
--env SEARCH_ALLOW_KEYLESS_FALLBACK=true \
-- npx -y @yoloyash/web-basicsAutomatic search uses only configured providers by default. Enabling SEARCH_ALLOW_KEYLESS_FALLBACK appends keyless Firecrawl, anonymous Exa MCP, and DuckDuckGo HTML. Searches are sequential and stop after the first provider returns renderable content. Empty responses fall through like provider errors. Keyless services are best-effort and may enforce their own rate limits or bot challenges.
To prioritize Brave and then a SearXNG instance before keyless fallback:
codex mcp add web-basics \
--env SEARCH_PROVIDER=auto \
--env BRAVE_SEARCH_API_KEY=your-subscription-token \
--env SEARXNG_URL=http://127.0.0.1:8088 \
--env SEARCH_ALLOW_KEYLESS_FALLBACK=true \
-- npx -y @yoloyash/web-basicsTo pin SearXNG without fallback:
codex mcp add web-basics \
--env SEARCH_PROVIDER=searxng \
--env SEARXNG_URL=http://127.0.0.1:8088 \
-- npx -y @yoloyash/web-basicsFor another stdio MCP client:
{
"command": "npx",
"args": ["-y", "@yoloyash/web-basics"],
"env": {
"SEARCH_PROVIDER": "searxng",
"SEARXNG_URL": "http://127.0.0.1:8088"
}
}SEARCH_PROVIDER accepts auto, brave, searxng, firecrawl, exa, or duckduckgo. It defaults to searxng, and explicitly selected SearXNG defaults to http://127.0.0.1:8088. In automatic mode, Brave and SearXNG are included only when their corresponding configuration is set. SEARCH_ALLOW_KEYLESS_FALLBACK=true appends Firecrawl, Exa, and DuckDuckGo; it has no effect on explicitly selected providers.
Programmatic callers can enable the same policy with createWebBasics({ searchBackend: "auto", allowKeylessFallback: true }).
To use Brave Search instead:
codex mcp add web-basics \
--env SEARCH_PROVIDER=brave \
--env BRAVE_SEARCH_API_KEY=your-subscription-token \
-- npx -y @yoloyash/web-basicsBrave uses its official Web Search API. SearXNG searches retain a bounded two-minute cache. Brave and keyless providers coalesce concurrent identical requests but do not retain completed responses.
Tools
web_search
Searches the selected provider or automatic fallback chain.
query: search querylimit: optional result count from 1 to 10; defaults to 5recency: optionalday,week,month, oryearfiltermax_tokens: optional provider answer token captemperature: optional provider sampling temperaturenum_search_results: optional provider search breadth or local result cap from 1 to 10
The structured result uses a unified provider response contract:
{
"response": {
"provider": "firecrawl",
"sources": [
{
"title": "Example result",
"url": "https://example.com/result",
"snippet": "Example snippet"
}
],
"requestId": "request-id-if-provided",
"authMode": "keyless"
}
}response.provider identifies the provider that served the result. Providers may also return answer, citations, searchQueries, relatedQuestions, usage, model, requestId, and authMode. A successful response does not include previous failed attempts. If every provider fails, the MCP call returns Error: ... as normal text plus { response: { provider, sources: [] }, error } as structured content.
The root API returns the SearchResponse directly:
const web = createWebBasics({
searchBackend: "auto",
allowKeylessFallback: true,
});
const response = await web.webSearch({ query: "TypeScript 6", limit: 5 });
console.log(response.provider, response.sources);fetch_url
Fetches one public HTTP(S) URL.
url: URL to fetchstart_index: optional character offset; defaults to 0max_length: optional character limit from 1 to 20,000; defaults to 8,000
Supports readable web pages, PDFs, direct text formats, Reddit posts, and PNG, JPEG, WebP, or GIF images. When text is truncated, call the tool again with next_start_index.
Reddit posts use public old Reddit HTML for the rendered post and comments, with RSS as a fallback. Successful responses are cached by post ID for up to one hour while respecting stricter upstream cache directives.
Both tools expose MCP output schemas and return structured content alongside text content.
Safety And Scope
Public provider requests and fetched URLs are limited to safe HTTP(S) destinations. The server rejects URL credentials, unsafe DNS results and redirects, unsupported content types, and oversized responses. User-managed SearXNG endpoints may be private.
Keyless fallback is opt-in because search queries are sent to third-party services. Its order is Firecrawl, Exa, then DuckDuckGo; select one of those providers explicitly to use only that service.
This package does not provide JavaScript rendering, browser automation, crawling, authenticated page fetching, proxy routing, bundled search infrastructure, or answer synthesis.
Development
npm ci
npm test
npm pack --dry-runNormal tests do not access the public internet. Live smoke tests should explicitly select the provider being tested; Brave and SearXNG require their corresponding configuration.
Available Tools
2 toolsfetch_urlARead-onlyIdempotent
Fetch one public HTTP(S) URL. Returns clean Markdown for pages and Reddit posts, extracted PDF text, direct text data, or a supported image. Use start_index to continue truncated text.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Target URL | |
| max_length | No | Maximum text characters to return | |
| start_index | No | Character index to start text content from |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | |
| links | No | |
| title | No | |
| content | No | |
| metadata | No | |
| extractor | Yes | |
| pageCount | No | |
| truncated | No | |
| wordCount | No | |
| byteLength | No | |
| contentType | Yes | |
| start_index | No | |
| total_chars | No | |
| returned_chars | No | |
| fallback_reason | No | |
| next_start_index | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the tool read-only, idempotent, and non-destructive. The description adds useful behavior: it specifies supported content types (Markdown, PDF text, etc.) and discloses that text can be truncated, with a pointer to start_index for continuation. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero filler. The main action and return types are front-loaded, and the start_index hint is a separate, purposeful clause. Nothing extraneous.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of an output schema and the simple nature of the tool, the description covers the essential aspects: what it fetches, what it returns, and how to handle truncation. It does not mention error cases or rate limits, but those are not critical for correct invocation and are partially implied by the annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% describing all three parameters. The description supplements the start_index parameter by explicitly connecting it to truncated text continuation, which adds semantic value beyond the generic schema description. max_length and url are already well-documented in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Fetch') and the resource ('one public HTTP(S) URL'), and enumerates the output types. This unambiguously distinguishes it from the sibling web_search (which searches rather than fetches a known URL).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage: you should use this tool when you have a specific URL to fetch. However, it never explicitly contrasts with web_search or states when NOT to use it. The only usage hint provided is about start_index for continuing truncated text, which is a parameter-level instruction, not a tool-selection guideline.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
web_searchARead-onlyIdempotent
Run one web query through the first available search provider and return formatted source URLs plus the provider response.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Result limit | |
| query | Yes | Search query | |
| recency | No | Relative time filter | |
| max_tokens | No | Provider answer token cap when supported | |
| temperature | No | Provider sampling temperature when supported | |
| num_search_results | No | Requested search breadth or local result cap |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | |
| response | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, idempotentHint=true, and destructiveHint=false, covering safety and side-effect profiles. The description adds context about selecting the 'first available search provider' and returning both source URLs and provider response, but it doesn't disclose potential variability or failure modes. This modest additional context earns a 3 given the annotations carry the main behavioral load.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence that states the action, provider-selection behavior, and return format without any redundant words. It is concise and well-structured, earning a top score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The output schema exists (not shown but indicated), so return-value details are presumably covered there. The description covers the core operation and return format, and annotations address safety. It could mention the implication of 'first available provider' (e.g., result variability) but this is a minor gap. Overall, it is sufficiently complete for an agent to call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with all six parameters (query, limit, recency, max_tokens, temperature, num_search_results) having descriptions in the schema. The description adds no parameter-specific detail beyond what the schema provides, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (run one web query), the resource (through a search provider), and the outputs (formatted source URLs plus provider response). This is distinct from the sibling fetch_url, which implies fetching a specific URL, so the purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this tool is for searching, but it does not explicitly state when to use it vs. alternatives like fetch_url, nor does it mention exclusions or prerequisites. The context is clear enough that an agent would infer usage, but no explicit guidance is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v0.5.0- Changed
fetch_url3 fields changed- added
Input schema / properties / max_lengthAdded value: +{ + "default": 8000, + "description": "Maximum text characters to return", + "maximum": 20000, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / start_indexAdded value: +{ + "default": 0, + "description": "Character index to start text content from", + "minimum": 0, + "type": "integer" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "byteLength": { + "minimum": 0, + "type": "integer" + }, + "content": { + "type": "string" + }, + "contentType": { + "type": "string" + }, + "extractor": { + "enum": [ + "defuddle", + "readability", + "unpdf", + "reddit", + "text", + "image" + ], + "type": "string" + }, + "fallback_reason": { + "type": "string" + }, + "links": { + "items": { + "type": "string" + }, + "type": "array" + }, + "metadata": { + "additionalProperties": { + "type": [ + "string", + "number", + "boolean", + "null" + ] + }, + "type": "object" + }, + "next_start_index": { + "minimum": 0, + "type": "integer" + }, + "pageCount": { + "minimum": 1, + "type": "integer" + }, + "returned_chars": { + "minimum": 0, + "type": "integer" + }, + "start_index": { + "minimum": 0, + "type": "integer" + }, + "title": { + "type": "string" + }, + "total_chars": { + "minimum": 0, + "type": "integer" + }, + "truncated": { + "type": "boolean" + }, + "url": { + "type": "string" + }, + "wordCount": { + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "url", + "contentType", + "extractor" + ], + "type": "object" +}
- Changed
web_search5 fields changed- added
Input schema / properties / max_tokensAdded value: +{ + "description": "Provider answer token cap when supported", + "exclusiveMinimum": 0, + "type": "integer" +} - added
Input schema / properties / num_search_resultsAdded value: +{ + "description": "Requested search breadth or local result cap", + "maximum": 10, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / recencyAdded value: +{ + "description": "Relative time filter", + "enum": [ + "day", + "week", + "month", + "year" + ], + "type": "string" +} - added
Input schema / properties / temperatureAdded value: +{ + "description": "Provider sampling temperature when supported", + "type": "number" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "error": { + "type": "string" + }, + "response": { + "additionalProperties": false, + "properties": { + "answer": { + "type": "string" + }, + "authMode": { + "type": "string" + }, + "citations": { + "items": { + "additionalProperties": false, + "properties": { + "citedText": { + "type": "string" + }, + "title": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "required": [ + "url", + "title" + ], + "type": "object" + }, + "type": "array" + }, + "model": { + "type": "string" + }, + "provider": { + "enum": [ + "brave", + "duckduckgo", + "exa", + "firecrawl", + "none", + "searxng" + ], + "type": "string" + }, + "relatedQuestions": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requestId": { + "type": "string" + }, + "searchQueries": { + "items": { + "type": "string" + }, + "type": "array" + }, + "sources": { + "items": { + "additionalProperties": false, + "properties": { + "ageSeconds": { + "type": "number" + }, + "author": { + "type": "string" + }, + "publishedDate": { + "type": "string" + }, + "snippet": { + "type": "string" + }, + "title": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "required": [ + "url", + "title" + ], + "type": "object" + }, + "type": "array" + }, + "usage": { + "additionalProperties": false, + "properties": { + "inputTokens": { + "type": "number" + }, + "outputTokens": { + "type": "number" + }, + "searchRequests": { + "type": "number" + }, + "totalTokens": { + "type": "number" + } + }, + "type": "object" + } + }, + "required": [ + "provider", + "sources" + ], + "type": "object" + } + }, + "required": [ + "response" + ], + "type": "object" +}
2 tool updates
v1.0.0- First observed
fetch_url - First observed
web_search
TDQS
Scored across 2 tools
The two tools perform fundamentally different operations: one searches the web, the other fetches a specific URL. There is zero overlap in purpose, so an agent can clearly distinguish which tool to use for a given task.
Both tools use a verb_noun pattern ('web_search' and 'fetch_url'), which is consistent and readable. 'web_search' could be parsed as 'search the web' but the prefix 'web_' is used similarly, so the pattern is predictable. Minor deviation: 'web_search' vs 'fetch_url' both place the verb first, so it's actually consistent.
With only two tools, the server feels minimal, which is on the borderline for a dedicated web-basics server. Both tools are essential and non-redundant, but the count is thin—though it may be appropriate for a focused utility server.
For a 'web-basics' domain, search and fetch cover the core operations an agent would need. The fetch tool handles multiple content types and page truncation, which is good. Minor gaps exist (e.g., no way to submit forms or list search history), but these are not expected for a basics server.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Docs: https://docs.keenable.ai/mcp-server Keenable is a free, remote MCP server that gives agents access to the web index. Search the web with ranked results and date/site filters, then fetch any indexed page as clean markdown. Works out of the box with no account or API key.
- UnifAPIOAuthcom.unifapi
Hosted MCP server for live public-data APIs and Skills for AI agents.
Free remote MCP server for fetching public web pages through a rotating proxy pool.
Related MCP Servers
- FlicenseAqualityCmaintenanceMCP server that provides a search_web tool to query a self-hosted SearXNG instance and return structured web search results.1-
- FlicenseNot gradedqualityBmaintenanceA self-hosted MCP server providing private web search, web page fetching, and current date/time tools, powered by a bundled SearXNG instance for API-key-free local search.2-
- AlicenseAqualityBmaintenanceA self-hosted MCP server for web search with multi-engine support, combining search, URL fetching, and deep research along with proxy routing and deduplication.3MIT
- AlicenseAqualityAmaintenanceAn MCP server providing web search, image search, and page scraping tools to LLMs without requiring API keys.312MIT