Browse documentation
web_search: search the index
Search the agent-first web index. Returns metadata-only hits (url, host, snippet, score, trust and graph signals) — never the page body; fetch that with get_document when a snippet is not enough.
Behaviour
The query supports boolean operators: AND, OR, -term to exclude, and "exact phrase". Name a vertical to disambiguate, or omit it and the router picks one from the query.
The index is admission-controlled, so a small result set usually means the index holds little on the topic, not that the query was wrong. One exception: if `partial` comes back true, part of the corpus was unreachable and the answer really is incomplete.
Every filter below is also a query parameter on GET /search, with the same name and the same meaning. IN-list filters accept either an array or a comma-separated string.
Costs 1 credit.
Arguments
inputSchema
| Name | Type | Description |
|---|---|---|
queryrequired | string | Boolean-capable: rust AND async, -python, "exact phrase" |
Filters
The other 31 arguments are the filter set, which is not this
tool's own. The same names and meanings are query parameters on GET /search, and what each one narrows is
written out in Filters and sorting rather than a
third time here. What is listed below is the part that differs over MCP: the JSON
type each argument accepts, which is what you need to build the arguments object.
| Name | Type |
|---|---|
authority | array | string |
collapse | "none" | "host" | "page" | "story" |
community | array | string |
content_type | array | string |
exclude_site | array | string |
facets | boolean |
fields | array | string |
from | integer |
lang | string |
langs | array | string |
limit | integer |
max_words | integer |
min_centrality | number |
min_host_rank | number |
min_independent_sources | integer |
min_quality | integer |
min_words | integer |
mode | "keyword" | "semantic" | "hybrid" |
prefer_authority | boolean |
prefer_recent | boolean |
published_from | integer |
published_to | integer |
safe | boolean |
site | string |
sort | "relevance" | "recency" | "host_rank" | "quality" | "published" | "words" | "centrality" |
source | "cc" | "delta" |
term | string |
tld | array | string |
to | integer |
topic | array | string |
vertical | string |
Argument shapes
The one argument that is not spelled the same on both transports is query, which is q as a query parameter.
Every other name matches.
8 arguments take either a JSON array or a comma-separated
string: authority, community, content_type, exclude_site, fields, langs, tld, topic. That is the one place the two transports differ in shape. A URL query string
cannot carry an array, so the REST form of these is always the comma-separated
one; an argument object can carry either.
Returns
A JSON payload in the text content block, and the same payload as
structuredContent for clients that support it.
outputSchema
| Name | Type | Description |
|---|---|---|
facets | object | Present only when facets=true |
moderequired | "keyword" | "semantic" | "hybrid" | The mode actually used |
partial | boolean | true when at least one shard failed or timed out — the answer is short because a slice of the corpus was unreachable, NOT because that is all there is. Never treat a partial result as complete. |
resultsrequired | object[] | — |
routedrequired | boolean | true when the router chose the vertical, false when you named it |
totalrequired | integer | — |
vertical | string | null | The vertical actually queried |
Calling it
Over Streamable HTTP, with the required arguments filled in:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "web_search",
"arguments": {
"query": "<query>"
}
}
} Most clients do this for you — see Connect a client. To drive it by hand, complete the startup lifecycle first.
The same call over REST
If your client does not speak MCP, this capability is
GET /search, taking the same parameters and
returning the same body.
curl -H "x-api-key: $UNLOB_API_KEY" \
"https://api.unlob.com/search?q=<query>"