octen-mcp
OfficialThis MCP server gives AI agents live web search and URL extraction with rich metadata, plus optional beta image/video search.
search— real-time web search with domain/text/language/time filters, highlights, full content, and optional images.news_search— news-focused search using the same options assearch.broad_search— decompose a query into multiple sub-queries, run them concurrently, and return grouped results for broad research.extract— fetch 1–20 URLs and return clean markdown/text content, page category and structure labels, and optional query-based highlights.image_search(beta) — find images by text, reference image URL, or base64 data, with optional design-focused UI snippets.video_search(beta) — find videos by text query with time filters and safety controls.All tools support filtering, time windows, language selection, safe search, and custom timeouts; the server enforces parameter schemas before calling the API.
Click on "Deploy 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., "@octen-mcpFetch octen.ai and summarize the main product features"
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.
octen-mcp
MCP server for Octen. Plug it into Claude, Cursor, VS Code, Windsurf, or any MCP client to give your agent live web search and URL extraction.
Core capabilities:
search/news_search: search the live web with domain, text, language, and time filters.broad_search: decompose a query into multiple sub-queries, search them concurrently, and return results grouped per sub-query for broad coverage.extract: turn one or more URLs into clean, LLM-ready content.image_search(In Beta — contact us for beta access): search the web for images by text query, by a reference image URL, or by base64 image data — exactly one of the three.video_search(In Beta — contact us for beta access): search the web for videos by text query.
What makes Octen useful for agents is that extract returns more than page text. Each successful result also includes:
category: what the page is aboutpage_structure: what kind of page it ishighlights: ranked snippets when you pass aquery
That lets an agent skip login walls, nav pages, and off-topic URLs before spending tokens on the full body.
Why Octen MCP
Fast
Web search averages 62ms. Fast enough for multi-step MCP workflows.
Accurate
Powered by SOTA text and VL embedding models. Better sources, fewer hallucinations.
Fresh
Live web data with minute-level updates. Useful for news, prices, and fast-moving pages.
Efficient
Clean highlights, optional full_content, and page labels keep model context relevant.
Related MCP server: Averra Extract MCP
Quick start
You need an OCTEN_API_KEY from octen.ai — or nothing at
all, if your client signs in over OAuth (see Signing in instead).
Two ways to connect. Both serve the same six tools.
Endpoint | When | |
Hosted (recommended) |
| Nothing to install or update. Works with any client that speaks remote MCP. |
Local |
| Clients without remote support, air-gapped setups, or when you want the process on your own machine. |
Node compatibility (local only): 0.4.2 and later run on every supported Node (>= 18.17), including Node 26+. Versions 0.4.1 and below fail every call on hosts whose embedded undici is v8+ (Node 26 and later) with
Network error … code=UND_ERR_INVALID_ARG cause=invalid onError method— if you see that error, upgrade the package (or run on Node <= 24).
Connect to the hosted endpoint
Passing your key
Three ways, tried in this order. Prefer a header — a key in a URL is
exposed to proxy logs, browser history and Referer headers.
Form | Use when |
| The default. |
| Your client only offers one header field. |
| Your client accepts nothing but a URL. |
Or use OAuth and paste no key at all — see Signing in instead.
By client
Claude Code — install the plugin. It brings the hosted server together with
two skills, octen-web-search (routes a request to the right tool) and
octen-research (multi-source research pipeline):
claude plugin marketplace add Octen-Team/octen-mcp
claude plugin install octen@octenOr from inside a session: /plugin marketplace add Octen-Team/octen-mcp, then
/plugin install octen@octen.
The plugin carries no credential. The first call is answered 401 and Claude
Code walks you through the OAuth sign-in — run /mcp if you want to start it
yourself. To register the server on its own instead, with a key:
claude mcp add --transport http octen https://mcp.octen.ai/mcp --header "x-api-key: your-key-here"Cursor — ~/.cursor/mcp.json
{
"mcpServers": {
"octen": {
"url": "https://mcp.octen.ai/mcp",
"headers": { "x-api-key": "your-key-here" }
}
}
}VS Code — .vscode/mcp.json (workspace) or the user config. Note servers,
not mcpServers, and the explicit type:
{
"servers": {
"octen": {
"type": "http",
"url": "https://mcp.octen.ai/mcp",
"headers": { "x-api-key": "your-key-here" }
}
}
}Codex
codex mcp add octen --url https://mcp.octen.ai/mcp --header "x-api-key: your-key-here"Windsurf — ~/.codeium/windsurf/mcp_config.json. The key is serverUrl,
not url:
{
"mcpServers": {
"octen": {
"serverUrl": "https://mcp.octen.ai/mcp",
"headers": { "x-api-key": "your-key-here" }
}
}
}Gemini CLI — ~/.gemini/settings.json. The key is httpUrl:
{
"mcpServers": {
"octen": {
"httpUrl": "https://mcp.octen.ai/mcp",
"headers": { "x-api-key": "your-key-here" }
}
}
}Claude Desktop takes the URL directly — no config file, no bridge. In
Settings → Connectors, click Add custom connector, name it Octen, and
enter:
https://mcp.octen.ai/mcpLeave the Advanced settings empty: the OAuth Client ID and Secret fields are for servers that cannot register a client on their own, and ours can. Claude will offer to sign you in, and an Octen key is issued to that connection when you approve.
The connector dialog has no field for request headers, so an API key goes in the URL instead:
https://mcp.octen.ai/mcp?octenApiKey=your-key-hereSigning in is the better of the two — a URL is not a secret-carrying medium, and the sign-in flow can be revoked from your account without editing anything on this side. Note also that Claude connects from Anthropic's servers rather than from your machine, so a self-hosted deployment has to be reachable from the public internet for this to work at all; a private one wants the bridge below.
Clients that only speak stdio (Zed, Warp, Raycast, Cline) reach a remote
server through the mcp-remote bridge. Note there is no space after the
colon in --header — the value is split on the first one:
{
"mcpServers": {
"octen": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://mcp.octen.ai/mcp",
"--header", "x-api-key:your-key-here"
]
}
}
}If a client cannot pass a header at all and takes only a URL, put the key in
the URL instead: https://mcp.octen.ai/mcp?octenApiKey=your-key-here.
Signing in instead
If the deployment is configured with an authorization server — the hosted one
is — a request with no credential is answered 401 +
WWW-Authenticate: Bearer resource_metadata="…". That is the signal MCP
clients use to start an OAuth flow, so a client that supports OAuth will offer
to sign you in rather than ask for a key.
To move a connection that already has a key onto OAuth, point it at
https://mcp.octen.ai/mcp/oauth (or append ?login). That path issues the
challenge even when a key is present, which is the only way to trigger the
switch — with a key attached, the ordinary endpoint has no reason to.
Loading fewer tools
?tools=search,extract limits a connection to the tools you name, for both
tools/list and tools/call:
https://mcp.octen.ai/mcp?tools=search,extractClients load every advertised tool's full schema into the model's context, so
narrowing the set is a real saving when you only need one or two. An unknown
name is refused with a 400 listing the valid ones, rather than a connection
that quietly comes up short.
Run it locally instead
{
"mcpServers": {
"octen": {
"command": "npx",
"args": ["-y", "octen-mcp"],
"env": { "OCTEN_API_KEY": "your-key-here" }
}
}
}
Agent | One-line install |
Claude Code |
|
Codex |
|
Gemini CLI |
|
VS Code |
|
Cursor | Add to Cursor (then edit the key), or use the JSON above in |
Claude Desktop | No CLI. For the hosted endpoint use Settings → Connectors → Add custom connector (above); for a local install, the config file (below) |
Config file locations
Claude Desktop:
~/Library/Application\ Support/Claude/claude_desktop_config.json— only needed for a local (stdio) install; the hosted endpoint is added as a connector insteadCursor:
~/.cursor/mcp.jsonVS Code workspace:
.vscode/mcp.json(useserversinstead ofmcpServers)Windsurf:
~/.codeium/windsurf/mcp_config.jsonGemini CLI:
~/.gemini/settings.jsonCline / other clients: paste it into that client's MCP settings
Troubleshooting
401 on every call. No credential reached the server. Check the header
name — x-api-key, or Authorization: Bearer — and, if you are using
mcp-remote, that there is no space after the colon in --header.
The tools do not appear. Most clients read MCP config once at startup;
restart the client after editing it. If the config uses the wrong key for your
client (url vs serverUrl vs httpUrl), the server is never contacted at
all — see the per-client sections above.
406 Not Acceptable. The request's Accept header must list both
application/json and text/event-stream. Clients do this for you; hand-rolled
curl probes usually do not, and the resulting 406 looks like an auth failure.
400 mentioning tools. A name in ?tools= is not one this deployment
serves. The error lists the ones that are.
A tool errors with code=403 … beta access. image_search and
video_search are in Beta and enabled per account; the message says how to
request it.
Errors name what happened. A failed call reports which dependency failed
and why — a timeout, a connection code, an expired token and by how long — plus
Octen's own request_id where the API returned one. Quote that id in a support
request; it is the one an engineer can look up.
Tools
Tool | What it does | Best for |
| Search the live web with domain, text, language (ISO 639-1), time, and content controls | a single focused web search |
| Same engine as | current events and timely reporting |
| Decompose a query into up to | research-style, multi-angle coverage |
| Fetch 1-20 URLs and return clean content, labels, and optional highlights | summarization, RAG, fact lookup |
| In Beta — contact us for beta access. Search the web for images by text query (optional reference | finding pictures, photos, visual references |
| In Beta — contact us for beta access. Search the web for videos by text query | finding videos, clips, footage |
These six are the whole surface, on purpose. Embeddings, chat completions, Answer and Research are Octen APIs that this server deliberately does not expose — reach them through the Python SDK or the CLI. A tool an agent can see is a tool it will try, so the roster stays the set that earns its place in a tool list.
Reference docs:
Parameters
Transcribed from the schemas each tool publishes — and those are enforced, so an out-of-contract value is refused before any call is made, with a message naming the field. The limits track the API reference; a test fails if the two drift apart.
image_search takes exactly one of query, image_url or image_data.
query must be non-empty: an empty string is refused by the schema, and a
whitespace-only one by the handler. Neither reaches the API.
timeout means two different things. On search, news_search,
broad_search, image_search and video_search it is this server's own HTTP
deadline for the call — it is removed from the request body and never sent to
the API. On extract it is the API's documented per-URL fetch budget
(1-60s) and does travel in the body; the local deadline for an extract call is
derived from it with headroom, so raising timeout raises both.
Overlapping include_domains and exclude_domains are passed through as
given. The API currently answers a domain listed in both with a validation
error; the published
reference describes exclusion
taking precedence. Until those agree, this server neither silently drops nor
reorders your filters — you get the API's answer.
search
Parameter | Type | Required | Limits | Default |
| string | yes | 1–500 chars | |
| string |
|
| |
| integer | 1–100 |
| |
| array | ≤1200 items; each ≤60 | ||
| array | ≤1200 items; each ≤60 | ||
| array | ≤5 items; each ≤30 | ||
| array | ≤5 items; each ≤30 | ||
| string |
|
| |
| string |
| ||
| string | |||
| string | |||
| string |
|
| |
| string |
|
| |
| array |
| ||
| object |
| ||
| object |
| ||
| boolean |
| ||
| integer | 1–60 |
news_search
Parameter | Type | Required | Limits | Default |
| string | yes | 1–500 chars | |
| integer | 1–100 |
| |
| array | ≤1200 items; each ≤60 | ||
| array | ≤1200 items; each ≤60 | ||
| array | ≤5 items; each ≤30 | ||
| array | ≤5 items; each ≤30 | ||
| string |
|
| |
| string |
| ||
| string | |||
| string | |||
| string |
|
| |
| string |
|
| |
| array |
| ||
| object |
| ||
| object |
| ||
| boolean |
| ||
| integer | 1–60 |
broad_search
Parameter | Type | Required | Limits | Default |
| string | yes | 1–500 chars | |
| integer | 1–30 |
| |
| string |
|
| |
| integer | 1–100 |
| |
| array | ≤1200 items; each ≤60 | ||
| array | ≤1200 items; each ≤60 | ||
| array | ≤5 items; each ≤30 | ||
| array | ≤5 items; each ≤30 | ||
| string |
|
| |
| string |
| ||
| string | |||
| string | |||
| string |
|
| |
| string |
|
| |
| array |
| ||
| object |
| ||
| object |
| ||
| boolean |
| ||
| integer | 1–300 |
extract
Parameter | Type | Required | Limits | Default |
| array | yes | ≤20 items; each ≤2048 | |
| string | ≤500 chars | ||
| integer | 300–31536000 |
| |
| string |
|
| |
| integer | 1–60 |
| |
| boolean |
| ||
| boolean |
| ||
| boolean |
|
image_search
Parameter | Type | Required | Limits | Default |
| string | ≤500 chars | ||
| string | |||
| string | ≤5242880 chars | ||
| string |
|
| |
| integer | 1–10 |
| |
| array | |||
| array | |||
| string |
|
| |
| object |
| ||
| integer | 1–60 |
video_search
Parameter | Type | Required | Limits | Default |
| string | yes | 1–500 chars | |
| integer | 1–10 |
| |
| string |
| ||
| string | |||
| string | |||
| string |
|
| |
| integer | 1–60 |
Keep the tools always on (optional)
In clients with MCP tool search enabled (the Claude Code default), tools are
deferred — the model runs a ToolSearch step to load them on demand. If you'd
rather have the Octen tools resident from the first turn (no discovery step), set
alwaysLoad on the server in your .mcp.json (Claude Code v2.1.121+):
{
"mcpServers": {
"octen": {
"command": "npx",
"args": ["-y", "octen-mcp"],
"env": { "OCTEN_API_KEY": "your-key-here" },
"alwaysLoad": true
}
}
}Each always-loaded tool uses context on every turn, and alwaysLoad blocks startup
until the server connects (capped at the ~5s connect timeout), so reserve it for tools
you hit constantly. To keep the cost down, mark just the highest-traffic tools — e.g.
search and broad_search — with "anthropic/alwaysLoad": true in each tool's _meta,
leaving the rest deferred.
Why agents like this
Most extract tools stop at "here is the page body." Octen helps one step earlier:
Skip bad pages early:
page_structure.primary == "No Main Content"tells the agent it hit a login wall, empty shell, or similar non-content page.Filter by topic early:
categoryhelps a pipeline ignore pages outside the target vertical before embedding or summarizing.Use less context:
queryreturnshighlightswhen the user wants a specific fact instead of the full page.
For the full decision tree and integration patterns, see docs/best-practices.md.
Example prompts
Fetch octen.ai and summarize the main product features.Search for recent MCP news from the last week.Fetch these URLs and only summarize the ones whose category is Finance.Search site:docs.anthropic.com prompt caching and return only the relevant highlights.
Self-hosting the HTTP server
The hosted endpoint above runs this same code; you can run it yourself instead:
PORT=8080 npx -y -p octen-mcp octen-mcp-http # or: octen-mcp-http after a global installEndpoints: POST /mcp (stateless Streamable HTTP) and GET /healthz. Stateless
by design — there is no session to lose, so scaling is a matter of running more
copies behind a load balancer. Credentials travel per request and never come
from the server's own environment: a request without one fails rather than
quietly spending the host's key.
Authorization is off unless you configure it. Set both
OCTEN_OAUTH_AUTHORIZATION_SERVER and OCTEN_MCP_RESOURCE and the server
advertises RFC 9728 protected-resource metadata and answers uncredentialed
requests with a 401 challenge. Leave them unset and it advertises nothing —
an instance should never point clients at an authorization server it does not
have — and a missing key surfaces at call time instead.
Argument validation. Each tool's declared inputSchema is enforced, not
just advertised: types, ranges, string lengths, array sizes, enums, required
parameters, and the property list itself. An out-of-contract call is refused
with a message naming the field, before anything is sent to the API.
Sending an image as base64. image_search accepts image_data up to 5MB
encoded, which travels inside the JSON-RPC body. OCTEN_MCP_MAX_BODY defaults
to 6 MiB to make that work unconfigured; OCTEN_MCP_MAX_INFLIGHT_BODY (24 MiB)
separately bounds what all in-flight bodies hold at once, since a per-request
cap does nothing about many concurrent ones.
Environment variables
Variable | Required | Default | Notes |
| yes | — | |
| no |
| |
| no | on | Set to |
| no | — | Honoured since 0.4.0. Node's built-in |
| no |
| How long an idle connection is kept for reuse. undici's own default of 4s meant nearly every call re-paid a full TLS handshake (~515ms measured). 60s is measured against |
| no |
| Upper bound on the above when the origin advertises its own |
| no |
| Ceiling on establishing the outbound connection to |
| no | on | Set to |
| no | off | Opt into HTTP/2. Measured no faster for the usual one-request-at-a-time pattern, and not reliable through every CONNECT proxy — worth trying if you issue many tool calls in parallel. |
| no | off | Request tracing on stderr (stdout carries MCP framing). See below. |
Remote HTTP form only
These are read only by octen-mcp-http; the stdio entry ignores them.
Variable | Required | Default | Notes |
| no |
|
|
| no | human text |
|
| no |
| Per-request body cap, in bytes, enforced on bytes received. Over it: |
| no |
| Ceiling on the total bytes all in-flight bodies hold at once. The per-request cap stops one huge request; this stops many ordinary ones. Over it: |
| no |
| After a |
| no |
| On |
| no | — | Plugin-directory domain-verification token. When set, |
OAuth. Off unless both of the first two are set, so an instance never advertises an authorization server it does not have.
Variable | Required | Default | Notes |
| for OAuth | — | Authorization server base URL. Compared byte-for-byte against the token's |
| for OAuth | — | This deployment's public URL, e.g. |
| for OAuth | — | Internal endpoint that exchanges a grant for an API key. Must be reachable privately; a public address will not serve it. |
| for OAuth | — | Shared secret sent to that endpoint as |
| no |
| How long a resolved grant is reused. This is the revocation-propagation window: a token revoked now keeps working for up to this long. |
| no |
| Floor between JWKS refetches triggered by an unknown key id. The trigger is an unverified token header, so without a floor each such request becomes one request to the authorization server. Lowering it widens that by the same ratio. |
Setting these in Claude Desktop (and where the logs go)
MCP servers do not inherit your shell environment. Claude Desktop spawns them
with HOME, LOGNAME, PATH, SHELL and USER — and nothing else except what
you put in the server's env block. A proxy configured system-wide will not be
picked up; it has to be named explicitly, alongside the API key:
{
"mcpServers": {
"octen": {
"command": "npx",
"args": ["-y", "octen-mcp"],
"env": {
"OCTEN_API_KEY": "your-key-here",
"HTTPS_PROXY": "http://proxy.example:8080"
}
}
}
}Restart Claude Desktop after editing the config — it reads it at launch.
Server output lands in:
macOS:
~/Library/Logs/Claude/mcp-server-octen.logWindows:
%APPDATA%\Claude\logs\mcp-server-octen.log
Everything the server writes to stderr, including the tracing below, goes there.
Diagnosing a slow or failing call
Add "OCTEN_MCP_DEBUG": "1" to the env block above while you are investigating,
and take it out afterwards — the client appends this to a log file that is
never rotated, so leaving it on grows that file for the life of the install.
With it on, every call is traced to stderr:
[octen-mcp 2026-08-14T04:36:36.219Z] call #1 received tool=search
[octen-mcp 2026-08-14T04:36:36.637Z] connect #1 established to api.octen.ai in 410ms peer=203.0.113.10:443 tls=TLSv1.3 alpn=http/1.1
[octen-mcp 2026-08-14T04:36:37.155Z] /search attempt=1 status=200 elapsed=935ms socket=new request_id=42cd56a5-…
[octen-mcp 2026-08-14T04:36:37.157Z] call #1 returning tool=search handler_total=938msEach field answers a specific question:
call #N receivedtimestamp — when the call reached this process. Subtract it from the time your MCP client issued the tool call: the difference is time spent entirely outsideocten-mcp, in the host or in whatever relays between them. A client-side stopwatch alone cannot separate that from time we are responsible for.connect … established in Xms— a handshake happened, and what it cost.connect FAILEDnames the phase and error code instead.peer=/tls=/alpn=— which address the connection actually reached (the API hostname is anycast, so the hostname alone cannot tell you which edge), and the negotiated TLS version and protocol — a mismatch there otherwise presents as an unexplained slow or failed handshake.socket=new/socket=reused— whether this call paid for a handshake. This is the difference between "the service is slow" and "the connection was thrown away between calls".elapsedvshandler_total— time in the HTTP request vs time in the tool handler. A large gap means the cost is in request assembly or response formatting, not the network.request_id— in this trace only: the client-generated correlation id, stable across the retry, tying a call's attempts together. It never appears in user-facing error messages, deliberately: Octen support cannot look it up (the gateway does not record the header), and an id labelledrequest_idreads like one they could. Error messages carry only ids verified searchable on Octen's side — today that is exactly one: the server's ownrequest_idfrom an API error envelope.
Failures name the cause rather than fetch failed:
Network error calling Octen Search: code=ECONNREFUSED cause=connect ECONNREFUSED 203.0.113.9:443
address=203.0.113.9:443 — could not establish a connection.
If this machine requires an HTTP proxy, set HTTPS_PROXY.UND_ERR_CONNECT_TIMEOUT means the connection was never established, ECONNRESET
means it was established and then torn down, and ENOTFOUND means DNS — three
different problems with three different owners.
Request timeouts: search and the media tools default to 30s, broad_search to 120s (raisable to 300s),
and extract to its per-URL budget plus headroom. The search tools accept a
timeout parameter to override; extract's timeout is the server-side,
per-URL fetch budget, so the client ceiling is derived from it rather than
equal to it. The automatic retry draws down the same deadline as the first
attempt, so the stated timeout bounds the whole call, retry included.
Local development
git clone https://github.com/Octen-Team/octen-mcp.git
cd octen-mcp
npm install
npm run build
OCTEN_API_KEY=<key> npm run inspectMore docs
Best practices for agent integration: docs/best-practices.md
Search API reference: docs.octen.ai/api-reference/search
Extract API reference: docs.octen.ai/api-reference/extract
License
MIT © Octen
Available Tools
6 toolsbroad_searchARead-only
Search the web across many angles in one call — for comparisons, research, surveys, and questions with several distinct parts. Expands your question into multiple sub-queries and runs them concurrently.
USE WHEN the question has multiple distinct parts or entities that one search cannot cover:
comparing vendors / products / pricing across many sources
literature reviews, market or landscape surveys
open-ended "what are the options for X" / "how do people solve Y"
a question that clearly decomposes into 3+ independent sub-questions
multi-angle questions about recent events ("what shipped across the industry this month") — set topic=news, do NOT loop news_search
DO NOT USE for:
a single fact, entity, or document → use
searchre-running a disappointing search → do NOT call broad_search twice; follow up with a targeted
searchorextracton the specific gapsreading a page you already have the URL for → use
extracta straight A-vs-B comparison of two known entities → two targeted
searchcalls are cheaper and more controllable
COST: fans out into max_queries concurrent searches — roughly Nx the cost and notably higher latency than a single search. When in doubt, prefer search.
QUERY: pass one natural-language question (max 500 chars). Resolve pronouns and references from the conversation first — "how does it compare to the other one" is a useless query. Do NOT pre-split into sub-queries; that is this tool's job. For broader coverage raise max_queries rather than calling repeatedly. Per-sub-query options (count, topic, language filter, domain / text filters, time window, highlight / full_content, media) match search and apply to every sub-query.
RESULTS are grouped per sub-query and NOT deduplicated — the same URL may appear under several sub-queries.
max_queries: 3-5 focused comparison (2-3 entities) | 5-10 multi-facet research | 10-20 landscape scan | 20-30 exhaustive survey
For a single focused lookup use search; to read a specific page use extract.
keywords: web search, search the web, look up, find information, research, compare, comparison, versus, alternatives, options, landscape, survey, market research, pricing, latest, current information, multi-part question
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | Number of results to return (1-100). Default 5. | |
| query | Yes | Non-empty search query. Max 500 chars. | |
| topic | No | Search category: `general` for broad web search, `news` for news-focused results. Default general. | general |
| format | No | Format of returned content. Default text. | text |
| timeout | No | Request timeout in seconds (1-300). Defaults to 120s if unset. Raise it for large `max_queries` surveys, which legitimately take longer. | |
| end_time | No | Upper bound for the time window, ISO 8601. | |
| language | No | Languages to filter results by, as ISO 639-1 codes. Empty = no filter. | |
| highlight | No | Return a ranked highlighted snippet per result. Omit to use the server default. | |
| safesearch | No | Adult-content filter. Default strict. | strict |
| start_time | No | Lower bound for the time window, ISO 8601 (e.g. '2025-01-01T00:00:00Z'). | |
| time_basis | No | Which timestamp the time window filters against: page `published` date, last `crawled` date, or `auto`. Default auto. | auto |
| time_range | No | Relative time window (e.g. `week`, `month`). Mutually exclusive with `start_time`/`end_time` — if both are given, the absolute range wins. | |
| max_queries | No | Upper bound on the number of sub-queries generated (1-30). Default 5 — raise toward 30 for surveys / deeper research, lower for a tighter search. | |
| exclude_text | No | Drop results whose content contains any of these strings. Max 5, each ≤30 chars. | |
| full_content | No | Return the cleaned full page body per result. Heavier than `highlight` — use only when the snippet isn't enough. Omit to use the server default (off). | |
| include_text | No | Only return results whose content contains all of these strings. Max 5, each ≤30 chars. | |
| include_images | No | Return image URLs (and a cover image) found on each result page. | |
| exclude_domains | No | Drop results from these domains. Max 1200, each ≤60 chars. | |
| include_domains | No | Only return results from these domains (e.g. 'arxiv.org'). Max 1200, each ≤60 chars. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Although annotations already mark readOnlyHint=true and destructiveHint=false, the description adds valuable behavioral disclosures: it fans out into max_queries concurrent searches, costs roughly Nx a single search, has notably higher latency, returns results grouped per sub-query, and does NOT deduplicate URLs. The description also warns that repeated calls should be avoided and that raising max_queries is preferred over looping. This significantly exceeds what the annotations convey and helps an agent predict the tool's real-world behavior and cost.
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 long but earns its length: the most essential behavioral fact (expands into concurrent sub-queries) is front-loaded in the first sentence, followed by structured USE WHEN / DO NOT USE sections, a cost warning, and targeted parameter guidance. Formatting with clear section headers and bullet-like lines makes the routing logic and warnings easy for an agent to parse. Every sentence carries decision-relevant information; nothing is filler.
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?
For a 19-parameter, sibling-rich tool with no output schema, the description is remarkably complete. It covers what the tool does, when to select it over each sibling, its cost and latency profile, its non-deduplication behavior, how to phrase the query, how to scale coverage via max_queries, that per-query options apply globally, and when to raise the timeout for large surveys. There is no significant missing piece that an agent would need to safely and effectively invoke this tool.
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%, so the schema already documents all 19 parameters fully. The description still adds meaningful semantics: it explains that per-sub-query options (count, topic, language filter, domain/text filters, time window, highlight/full_content, media) match `search` and apply to every sub-query, and it gives a scale of recommended max_queries values for different research depths. It also clarifies that the `query` should be a single natural-language question and must not be pre-split. This is strong added value beyond the schema, though it does not walk through the semantics of every individual parameter, which is why it stays a 4 rather than a 5.
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 opens with a specific verb and resource: 'Search the web across many angles in one call', then anchors it with concrete use cases (comparisons, research, surveys, multi-part questions) that distinguish it from a plain web search. It explicitly establishes the tool's unique behavior — expanding a question into multiple concurrent sub-queries — so an agent can clearly recognize what broad_search is for and how it differs from siblings like search.
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?
This is exemplary routing guidance. The description has a full 'USE WHEN' list with concrete scenarios, a 'DO NOT USE for' list that names the correct alternative tool for each case, an explicit note not to call broad_search twice after a disappointing result, and closing routing reminders pointing to `search` and `extract`. An agent gets clear decision criteria for using broad_search versus each sibling without needing external information.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
extractARead-only
Read one or more web pages by URL and return clean, LLM-ready content (markdown or text). By default (no query) it returns each page's full content — this is what you want in almost all cases. Only pass query when the user explicitly asks to fetch relevance-ranked snippets for a specific topic; doing so returns highlights INSTEAD of the full body, so the content will be partial. Every result also includes a category (topical) and page_structure (typology) classification. Bare hosts like 'octen.ai' are auto-normalized to https. Cached when fresh.
Use this when you already have the URL(s). To find pages first, use search or broad_search.
keywords: read page, fetch url, scrape, page content, article text, parse webpage, extract, read article, url content, open link
| Name | Required | Description | Default |
|---|---|---|---|
| urls | Yes | URLs to extract. 1-20 per call, each ≤2048 chars. Bare hosts ok. | |
| query | No | Optional — leave UNSET in the normal case. When unset, each result returns the page's `full_content` (the complete text). Only set this when the user explicitly wants relevance-ranked snippets for a specific query/topic: setting it makes each result return `highlights` (ranked excerpts) and OMIT `full_content`, so the page body will be incomplete. Do not pass it just to focus a normal fetch. | |
| format | No | Output format. Default markdown. | markdown |
| timeout | No | Per-URL timeout in seconds (1-60). | |
| include_audio | No | Return audio URLs found on each page. | |
| include_images | No | Return image resources found on each page (also enables `cover_image` when the page has one). | |
| include_videos | No | Return video URLs found on each page. | |
| max_age_seconds | No | Maximum age of cached content in seconds. Default 24h. Lower this for time-sensitive pages (news / prices). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it read-only, open-world, and non-destructive, and the description adds meaningful behavioral details: query mode returns highlights instead of full body, bare hosts are auto-normalized to https, content is cached when fresh, and results include category and page_structure classifications.
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 front-loaded with the core purpose and default behavior, then the critical query warning, then routing guidance. Each sentence contributes a distinct fact; the keyword list is slightly redundant but aids discoverability.
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?
With no output schema, the description appropriately conveys the return shape by mentioning full_content, highlights, category, and page_structure. It also covers caching, URL handling, and sibling alternatives, giving an agent enough context to invoke 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%, so the baseline is 3. The description adds useful operational semantics beyond the schema, especially the query/full-content trade-off and bare-host normalization, though some parameter guidance duplicates the schema's own descriptions.
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?
Opens with a specific verb and resource: 'Read one or more web pages by URL and return clean, LLM-ready content (markdown or text).' It also distinguishes itself from search siblings by saying 'Use this when you already have the URL(s).'
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?
Explicitly states when to use the tool and when not to: 'Use this when you already have the URL(s). To find pages first, use search or broad_search.' It also specifies the only condition for passing query and warns that doing so returns partial content.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
image_searchARead-only
Find images on the web by text query OR by a reference image — returns ranked results (title, source page, dimensions, thumbnail, description, summary). In Beta; contact us to request beta access. Pass exactly one of: a text query, an image_url (a picture already on the web), or image_data (base64, for a picture you hold). Never more than one. Set topic to design for UI design references — each result then carries a structured style summary and an html_snippet for building/restyling frontends. Use this when the user wants pictures, photos, diagrams, screenshots, or visual references — not for general text web search.
keywords: find images, image search, photos, pictures, screenshots, visual reference, diagram, icon, illustration, UI design, reference image
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | Number of results to return (1-10). Default 5. | |
| query | No | Text query describing the images to find. Exactly one of `query`, `image_url` or `image_data` — never more than one. | |
| topic | No | Image category: `general` for broad image search, `design` for design / illustration oriented results. Default general. | general |
| timeout | No | Request timeout in seconds (1-60). Defaults to 30s if unset. | |
| image_url | No | Public image URL to search by visual similarity. Exactly one of `query`, `image_url` or `image_data` — never more than one. | |
| image_data | No | Base64-encoded image to search by visual similarity, for an image you hold rather than one already on the web. At most 5MB encoded; JPEG, PNG, WEBP, BMP, TIFF, ICO, DIB, ICNS or SGI. A `data:` URI is accepted — its payload is used. Exactly one of `query`, `image_url` or `image_data` — never more than one. | |
| safesearch | No | Adult-content filter. Default strict. | strict |
| html_snippet | No | Return an HTML snippet of the source context per result. Omit to use the server default. | |
| exclude_domains | No | Drop results from these domains. | |
| include_domains | No | Only return results from these domains (e.g. 'unsplash.com'). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond annotations by disclosing that the tool is in Beta and requires access, that results are ranked, and what fields are returned. It also clarifies the design-topic behavior (structured style summary and html_snippet) and the accepted image formats and size limit, giving the agent a realistic operational picture.
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 dense and well front-loaded, with the core function, key constraints, and usage guidance near the top. The trailing keyword list is somewhat redundant with the prose, but for a tool with 10 parameters and multiple modes, the length is justified and each section earns its place.
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?
There is no output schema, but the description compensates by enumerating the returned fields: title, source page, dimensions, thumbnail, description, summary, and html_snippet in design mode. It also covers access requirements, input modes, and the suggestion to use it for visual references, making the tool callable end-to-end without missing critical context.
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%, so the baseline is 3. The description adds meaning on top of the schema by explaining the `topic=design` effect on result structure, the 'pass exactly one' exclusivity rule, and the practical distinction between `image_url` and `image_data`. It does not need to restate every schema detail.
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 opens with a specific verb and resource — 'Find images on the web by text query OR by a reference image' — and lists the returned result fields. It clearly distinguishes image search from general text web search and from the sibling tools by stating exactly what kind of content it retrieves.
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?
It explicitly states when to use the tool: 'Use this when the user wants pictures, photos, diagrams, screenshots, or visual references — not for general text web search.' It also gives mode-specific guidance for `topic=design`, and explains the mutual-exclusivity rule for `query`, `image_url`, and `image_data` so an agent knows how to choose among them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
news_searchARead-only
Search recent news and return ranked articles (title, url, snippet) — current events, headlines, timely reporting. This is search locked to topic: news; same options as search (domain / text filters, language filter, time window, highlight / full_content, media) except topic, which is fixed to news.
For a single news lookup this is the right tool. For a multi-angle news question ("what shipped across the industry this month", "how are different outlets covering X"), use broad_search with topic=news instead of looping news_search.
keywords: news search, latest news, headlines, current events, breaking news, recent, today, this week, press coverage
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | Number of results to return (1-100). Default 5. | |
| query | Yes | Non-empty search query. Max 500 chars. | |
| format | No | Format of returned content. Default text. | text |
| timeout | No | Request timeout in seconds (1-60). Defaults to 30s if unset. | |
| end_time | No | Upper bound for the time window, ISO 8601. | |
| language | No | Languages to filter results by, as ISO 639-1 codes. Empty = no filter. | |
| highlight | No | Return a ranked highlighted snippet per result. Omit to use the server default. | |
| safesearch | No | Adult-content filter. Default strict. | strict |
| start_time | No | Lower bound for the time window, ISO 8601 (e.g. '2025-01-01T00:00:00Z'). | |
| time_basis | No | Which timestamp the time window filters against: page `published` date, last `crawled` date, or `auto`. Default auto. | auto |
| time_range | No | Relative time window (e.g. `week`, `month`). Mutually exclusive with `start_time`/`end_time` — if both are given, the absolute range wins. | |
| exclude_text | No | Drop results whose content contains any of these strings. Max 5, each ≤30 chars. | |
| full_content | No | Return the cleaned full page body per result. Heavier than `highlight` — use only when the snippet isn't enough. Omit to use the server default (off). | |
| include_text | No | Only return results whose content contains all of these strings. Max 5, each ≤30 chars. | |
| include_images | No | Return image URLs (and a cover image) found on each result page. | |
| exclude_domains | No | Drop results from these domains. Max 1200, each ≤60 chars. | |
| include_domains | No | Only return results from these domains (e.g. 'arxiv.org'). Max 1200, each ≤60 chars. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only, open-world, and non-destructive, so the description does not need to repeat that. It adds useful behavioral details beyond annotations: output is ranked articles with title/url/snippet, supports highlights/full content/images, and applies time-window and domain filters.
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 core description is concise and front-loaded with purpose and usage guidance. The trailing 'keywords' line is mildly redundant with the first sentence, but the overall structure is clean and easy to scan.
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 17 parameters and no output schema, the description adequately summarizes the return shape (ranked articles with title, url, snippet) and main capabilities (time windows, filtering, highlighting, full content, images). It does not specify response envelope details like pagination or error codes, but those are commonly implied in such tools and not critical for basic invocation.
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%, and each parameter has a clear explanatory description with defaults and constraints. The description adds extra semantic guidance for parameters like `full_content` (heavier than highlight, use only when snippet isn't enough) and `time_range` (mutually exclusive with absolute times).
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 tool searches recent news and returns ranked articles with title, url, and snippet. It explicitly distinguishes this tool from `search` (locked to topic news) and from `broad_search` (for single vs multi-angle queries).
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 gives concrete guidance on when to use this tool versus `broad_search`: use for a single news lookup, use `broad_search` for multi-angle questions. It also clarifies that this is `search` with topic fixed to news, so options are inherited from `search`.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchARead-only
Search the live web and return ranked results (title, url, snippet) — fast, fresh, real-time web search for one focused lookup. Set topic to news for news-focused results. Pass highlight to get a ranked snippet per result, or full_content to pull the cleaned page body inline (heavier — costs more context). Narrow with domain / text include-exclude filters, a language filter (ISO 639-1 codes), and a time window (published/crawled start_time/end_time, or a relative time_range). Set include_images to return image URLs per result.
USE FOR a single focused lookup: one fact, one entity, one document. If the question spans several independent subtopics, load and use broad_search instead — a sequence of search calls is slower and gives worse coverage than one fan-out. To read a page you already have the URL for, use extract.
keywords: web search, search the web, look up, find, check, fact, current information, latest, news, source, url, real-time
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | Number of results to return (1-100). Default 5. | |
| query | Yes | Non-empty search query. Max 500 chars. | |
| topic | No | Search category: `general` for broad web search, `news` for news-focused results. Default general. | general |
| format | No | Format of returned content. Default text. | text |
| timeout | No | Request timeout in seconds (1-60). Defaults to 30s if unset. | |
| end_time | No | Upper bound for the time window, ISO 8601. | |
| language | No | Languages to filter results by, as ISO 639-1 codes. Empty = no filter. | |
| highlight | No | Return a ranked highlighted snippet per result. Omit to use the server default. | |
| safesearch | No | Adult-content filter. Default strict. | strict |
| start_time | No | Lower bound for the time window, ISO 8601 (e.g. '2025-01-01T00:00:00Z'). | |
| time_basis | No | Which timestamp the time window filters against: page `published` date, last `crawled` date, or `auto`. Default auto. | auto |
| time_range | No | Relative time window (e.g. `week`, `month`). Mutually exclusive with `start_time`/`end_time` — if both are given, the absolute range wins. | |
| exclude_text | No | Drop results whose content contains any of these strings. Max 5, each ≤30 chars. | |
| full_content | No | Return the cleaned full page body per result. Heavier than `highlight` — use only when the snippet isn't enough. Omit to use the server default (off). | |
| include_text | No | Only return results whose content contains all of these strings. Max 5, each ≤30 chars. | |
| include_images | No | Return image URLs (and a cover image) found on each result page. | |
| exclude_domains | No | Drop results from these domains. Max 1200, each ≤60 chars. | |
| include_domains | No | Only return results from these domains (e.g. 'arxiv.org'). Max 1200, each ≤60 chars. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool readOnly and non-destructive. The description adds useful behavioral context: results are ranked and real-time, full_content is heavier and costs more context, and time_range is mutually exclusive with start_time/end_time. It does not add much beyond schema-stated details in places, and some claims like 'fast, fresh, real-time' are somewhat promotional, but overall it discloses meaningful behavior beyond the 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?
The description is front-loaded with purpose and use-for guidance, followed by parameter details and keywords. It is longer than average, with some redundancy such as repeating 'single focused lookup' and emphasizing 'fast, fresh, real-time,' but the content is dense and mostly earns its place given the tool's 18 parameters.
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?
Despite having no output schema, the description clearly states the return shape (title, url, snippet) and additional output modes (highlight, full_content, include_images). Combined with the fully self-documenting input schema and explicit routing to alternatives, an agent has enough context to invoke the tool correctly for a wide range of focused lookup tasks.
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%, so the structured schema already documents every parameter fully. The description paraphrases a few key parameters (topic, highlight, full_content, include_images) but adds little meaning beyond what the schema states, such as noting that full_content 'costs more context.' Since the schema carries the burden, baseline 3 is appropriate.
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 opens with a concrete verb, resource, and output: 'Search the live web and return ranked results (title, url, snippet).' It clearly frames the tool as a single focused lookup and implicitly distinguishes it from siblings like broad_search and extract by contrasting scope and use case.
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 explicitly says to use this for a single focused lookup and tells the agent to use broad_search for multi-subtopic questions and extract for pages already known by URL. However, it does not mention the news_search sibling even though it instructs setting topic=news for news-focused results, leaving a potential ambiguity about when to prefer news_search.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
video_searchARead-only
Find videos on the web by text query — returns ranked results (title, source page, cover image, duration, matching segment, authors, description). In Beta; contact us to request beta access. Pass a text query. Use this when the user wants to find videos, clips, footage, tutorials, or a specific moment within a video — not for general text web search.
keywords: find videos, video search, clips, footage, youtube, tutorial video, watch, movie, video clip
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | Number of results to return (1-10). Default 5. | |
| query | Yes | Text query describing the videos to find. | |
| timeout | No | Request timeout in seconds (1-60). Defaults to 30s if unset. | |
| end_time | No | Upper bound for the time window, ISO 8601. | |
| safesearch | No | Adult-content filter. Default strict. | strict |
| start_time | No | Lower bound for the time window, ISO 8601 (e.g. '2025-01-01T00:00:00Z'). | |
| time_range | No | Relative time window (e.g. `week`, `month`). Mutually exclusive with `start_time`/`end_time` — if both are given, the absolute range wins. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds useful behavioral context beyond that: it is in Beta, requires beta access to be requested, and returns ranked results with a specific set of fields. It does not cover rate limits, failure behavior, or authentication, but with annotations present the added detail is solid.
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 mostly tight and front-loaded: purpose, result fields, beta access, and usage guidance appear in the first four sentences. The trailing keyword list is somewhat redundant, but it is short and does not seriously bloat the definition.
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?
For a read-only search tool with seven fully documented parameters, the description covers the essential invocation (text query), the return shape (ranked results with fields), and an access caveat (Beta). It does not explain interactions like `time_range` versus `start_time`/`end_time`, but those are handled in the schema, and the return-field list is valuable because no output schema exists.
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%, and all parameters already have descriptive text, enums, ranges, and defaults. The description only repeats the `query` parameter ('Pass a text `query`'), which adds no meaning beyond what the schema already provides. This matches the baseline for fully-documented schemas.
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 opens with a specific verb and resource: 'Find videos on the web by text query.' It also lists the concrete result fields, making the tool's scope unmistakable. It explicitly distinguishes itself from general text web search, which differentiates it from sibling `search`-style tools.
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 clearly states when to use the tool: when the user wants videos, clips, footage, tutorials, or a specific moment inside a video. It also gives a clear exclusion ('not for general text web search'), but it does not explicitly name sibling alternatives such as `search` or `news_search`, so it stops short of full guidance.
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.
3 tool updates
v0.5.2- Changed
broad_search2 fields changed- changed
Input schema / properties / query / descriptionPrevious value: -"Search query. Max 500 chars."New value: +"Non-empty search query. Max 500 chars." - added
Input schema / properties / query / minLengthAdded value: +1
- Changed
news_search2 fields changed- changed
Input schema / properties / query / descriptionPrevious value: -"Search query. Max 500 chars."New value: +"Non-empty search query. Max 500 chars." - added
Input schema / properties / query / minLengthAdded value: +1
- Changed
search2 fields changed- changed
Input schema / properties / query / descriptionPrevious value: -"Search query. Max 500 chars."New value: +"Non-empty search query. Max 500 chars." - added
Input schema / properties / query / minLengthAdded value: +1
5 tool updates
v0.5.0- Changed
broad_search7 fields changed- changed
Input schema / properties / exclude_domains / descriptionPrevious value: -"Drop results from these domains. Max 150, each ≤30 chars."New value: +"Drop results from these domains. Max 1200, each ≤60 chars." - changed
Input schema / properties / exclude_domains / items / maxLengthPrevious value: -30New value: +60 - changed
Input schema / properties / exclude_domains / maxItemsPrevious value: -150New value: +1200 - changed
Input schema / properties / include_domains / descriptionPrevious value: -"Only return results from these domains (e.g. 'arxiv.org'). Max 1000, each ≤30 chars."New value: +"Only return results from these domains (e.g. 'arxiv.org'). Max 1200, each ≤60 chars." - changed
Input schema / properties / include_domains / items / maxLengthPrevious value: -30New value: +60 - changed
Input schema / properties / include_domains / maxItemsPrevious value: -1000New value: +1200 - removed
Input schema / properties / include_videosRemoved value: -{ - "default": false, - "description": "Return video URLs found on each result page.", - "type": "boolean" -}
- Changed
extract3 fields changed- added
Input schema / properties / max_age_seconds / maximumAdded value: +31536000 - changed
Input schema / properties / urls / descriptionPrevious value: -"URLs to extract. 1-20 per call. Bare hosts ok."New value: +"URLs to extract. 1-20 per call, each ≤2048 chars. Bare hosts ok." - added
Input schema / properties / urls / items / maxLengthAdded value: +2048
- Changed
image_search9 fields changed- removed
Input schema / properties / end_timeRemoved value: -{ - "description": "Upper bound for the time window, ISO 8601.", - "type": "string" -} - changed
Input schema / properties / html_snippet / properties / max_tokens / descriptionPrevious value: -"Max tokens per HTML snippet (min 100). Default 5000."New value: +"Max tokens per HTML snippet (100-100000). Default 5000." - added
Input schema / properties / html_snippet / properties / max_tokens / maximumAdded value: +100000 - added
Input schema / properties / image_dataAdded value: +{ + "description": "Base64-encoded image to search by visual similarity, for an image you hold rather than one already on the web. At most 5MB encoded; JPEG, PNG, WEBP, BMP, TIFF, ICO, DIB, ICNS or SGI. A `data:` URI is accepted — its payload is used. Exactly one of `query`, `image_url` or `image_data` — never more than one.", + "maxLength": 5242880, + "type": "string" +} - changed
Input schema / properties / image_url / descriptionPrevious value: -"Optional public image URL to search by reference image (visual similarity), in addition to the text `query`."New value: +"Public image URL to search by visual similarity. Exactly one of `query`, `image_url` or `image_data` — never more than one." - changed
Input schema / properties / query / descriptionPrevious value: -"Text query describing the images to find."New value: +"Text query describing the images to find. Exactly one of `query`, `image_url` or `image_data` — never more than one." - removed
Input schema / properties / start_timeRemoved value: -{ - "description": "Lower bound for the time window, ISO 8601 (e.g. '2025-01-01T00:00:00Z').", - "type": "string" -} - removed
Input schema / properties / time_rangeRemoved value: -{ - "description": "Relative time window (e.g. `week`, `month`). Mutually exclusive with `start_time`/`end_time` — if both are given, the absolute range wins.", - "enum": [ - "day", - "week", - "month", - "year", - "d", - "w", - "m", - "y" - ], - "type": "string" -} - removed
Input schema / requiredRemoved value: -[ - "query" -]
- Changed
news_search7 fields changed- changed
Input schema / properties / exclude_domains / descriptionPrevious value: -"Drop results from these domains. Max 150, each ≤30 chars."New value: +"Drop results from these domains. Max 1200, each ≤60 chars." - changed
Input schema / properties / exclude_domains / items / maxLengthPrevious value: -30New value: +60 - changed
Input schema / properties / exclude_domains / maxItemsPrevious value: -150New value: +1200 - changed
Input schema / properties / include_domains / descriptionPrevious value: -"Only return results from these domains (e.g. 'arxiv.org'). Max 1000, each ≤30 chars."New value: +"Only return results from these domains (e.g. 'arxiv.org'). Max 1200, each ≤60 chars." - changed
Input schema / properties / include_domains / items / maxLengthPrevious value: -30New value: +60 - changed
Input schema / properties / include_domains / maxItemsPrevious value: -1000New value: +1200 - removed
Input schema / properties / include_videosRemoved value: -{ - "default": false, - "description": "Return video URLs found on each result page.", - "type": "boolean" -}
- Changed
search7 fields changed- changed
Input schema / properties / exclude_domains / descriptionPrevious value: -"Drop results from these domains. Max 150, each ≤30 chars."New value: +"Drop results from these domains. Max 1200, each ≤60 chars." - changed
Input schema / properties / exclude_domains / items / maxLengthPrevious value: -30New value: +60 - changed
Input schema / properties / exclude_domains / maxItemsPrevious value: -150New value: +1200 - changed
Input schema / properties / include_domains / descriptionPrevious value: -"Only return results from these domains (e.g. 'arxiv.org'). Max 1000, each ≤30 chars."New value: +"Only return results from these domains (e.g. 'arxiv.org'). Max 1200, each ≤60 chars." - changed
Input schema / properties / include_domains / items / maxLengthPrevious value: -30New value: +60 - changed
Input schema / properties / include_domains / maxItemsPrevious value: -1000New value: +1200 - removed
Input schema / properties / include_videosRemoved value: -{ - "default": false, - "description": "Return video URLs found on each result page.", - "type": "boolean" -}
5 tool updates
v0.4.2- Changed
broad_search2 fields changed- changed
Input schema / properties / timeout / descriptionPrevious value: -"Request timeout in seconds (1-60)."New value: +"Request timeout in seconds (1-300). Defaults to 120s if unset. Raise it for large `max_queries` surveys, which legitimately take longer." - changed
Input schema / properties / timeout / maximumPrevious value: -60New value: +300
- Changed
image_search1 field changed- changed
Input schema / properties / timeout / descriptionPrevious value: -"Request timeout in seconds (1-60)."New value: +"Request timeout in seconds (1-60). Defaults to 30s if unset."
- Changed
news_search1 field changed- changed
Input schema / properties / timeout / descriptionPrevious value: -"Request timeout in seconds (1-60)."New value: +"Request timeout in seconds (1-60). Defaults to 30s if unset."
- Changed
search1 field changed- changed
Input schema / properties / timeout / descriptionPrevious value: -"Request timeout in seconds (1-60)."New value: +"Request timeout in seconds (1-60). Defaults to 30s if unset."
- Changed
video_search1 field changed- changed
Input schema / properties / timeout / descriptionPrevious value: -"Request timeout in seconds (1-60)."New value: +"Request timeout in seconds (1-60). Defaults to 30s if unset."
2 tool updates
v0.3.6- Added
news_search - Added
search
3 tool updates
v0.3.5- Changed
broad_search1 field changed- added
Input schema / properties / languageAdded value: +{ + "default": [], + "description": "Languages to filter results by, as ISO 639-1 codes. Empty = no filter.", + "items": { + "enum": [ + "ar", + "de", + "en", + "es", + "fr", + "hi", + "id", + "it", + "ja", + "ko", + "nl", + "pl", + "pt", + "ru", + "th", + "tr", + "vi", + "zh" + ], + "type": "string" + }, + "type": "array" +}
- Removed
news_search - Removed
search
4 tool updates
v0.3.4- Changed
broad_search1 field changed- removed
Input schema / properties / countryRemoved value: -{ - "default": "auto", - "description": "Follow ISO 3166, the International Standard for country codes and codes for their subdivisions (e.g. `US`, `JP`); `auto` (default) determines it automatically.", - "type": "string" -}
- Added
extract - Changed
news_search1 field changed- removed
Input schema / properties / countryRemoved value: -{ - "default": "auto", - "description": "Follow ISO 3166, the International Standard for country codes and codes for their subdivisions (e.g. `US`, `JP`); `auto` (default) determines it automatically.", - "type": "string" -}
- Added
search
4 tool updates
v0.3.3- Changed
broad_search1 field changed- added
Input schema / properties / countryAdded value: +{ + "default": "auto", + "description": "Follow ISO 3166, the International Standard for country codes and codes for their subdivisions (e.g. `US`, `JP`); `auto` (default) determines it automatically.", + "type": "string" +}
- Removed
extract - Changed
news_search1 field changed- added
Input schema / properties / countryAdded value: +{ + "default": "auto", + "description": "Follow ISO 3166, the International Standard for country codes and codes for their subdivisions (e.g. `US`, `JP`); `auto` (default) determines it automatically.", + "type": "string" +}
- Removed
search
4 tool updates
v0.3.1- Added
broad_search - Changed
extract2 fields changed- removed
Input schema / properties / include_faviconRemoved value: -{ - "default": false, - "description": "Return each page's favicon URL.", - "type": "boolean" -} - changed
Input schema / properties / include_images / descriptionPrevious value: -"Return image URLs found on each page."New value: +"Return image resources found on each page (also enables `cover_image` when the page has one)."
- Added
image_search - Added
video_search
3 tool updates
v0.2.2- Changed
extract1 field changed- changed
Input schema / properties / query / descriptionPrevious value: -"Optional intent-focused keywords. When set, each result returns `highlights` (most relevant snippets, ranked) instead of `full_content`."New value: +"Optional — leave UNSET in the normal case. When unset, each result returns the page's `full_content` (the complete text). Only set this when the user explicitly wants relevance-ranked snippets for a specific query/topic: setting it makes each result return `highlights` (ranked excerpts) and OMIT `full_content`, so the page body will be incomplete. Do not pass it just to focus a normal fetch."
- Added
news_search - Added
search
1 tool update
v0.1.0- First observed
extract
TDQS
Scored across 6 tools
Each tool targets a distinct retrieval modality (general search, fan-out research, news, page extraction, images, videos), and the descriptions draw explicit boundaries. The main ambiguity is that news_search is essentially search with topic=news, and broad_search can also operate in news mode, so the text-search tools could occasionally be confused.
Most tools follow a predictable <modifier>_search pattern (broad_search, news_search, image_search, video_search), with search as the base. extract breaks the pattern and the bare search is a slight deviation, but all names are lowercase snake_case and clearly signal their function.
Six tools is a well-scoped size for a web research server: each tool maps to a distinct retrieval task and none feels redundant or ornamental. This sits comfortably in the ideal range and avoids overwhelming an agent with overlapping capabilities.
The surface covers the full web-research workflow: finding pages via single or multi-angle search, filtering by news or media type, and extracting clean content from known URLs. There are no obvious dead ends, and the descriptions explicitly connect follow-up actions between search and extract.
Maintenance
Related MCP Connectors
Jina AI Reader/Search MCP — turn any URL into clean LLM-ready markdown, plus web search.
Clean Markdown and AI-readability scoring for any URL. Built for AI agents.
MCP server (stdio): fetch web pages as clean readable markdown via the AgentForge API
Converts any URL to clean, LLM-ready Markdown using real Chrome browsers
Related MCP Servers
- AlicenseAqualityCmaintenanceFetch URLs and return clean, LLM-ready markdown with metadata and layered prompt injection defense. Configurable timeouts, word limits, JS rendering, and link extraction. All-in-one MCP server + CLI.11MIT
- AlicenseAqualityDmaintenanceMCP server for Averra Extract — lets AI agents like Claude, Cursor, and ChatGPT convert any webpage into clean, LLM-ready Markdown.551 npmMIT
- AlicenseAqualityBmaintenanceWeb extraction MCP server for AI agents. Extract structured data from any URL with built-in Cloudflare bypass, JavaScript rendering, and intelligent parsing. Returns clean markdown or JSON.5794 npm2MIT
- AlicenseAqualityDmaintenanceMCP Server for Web2MD — convert webpage URLs to clean Markdown from Claude Desktop, Cursor, or any MCP-compatible agent.613 npmMIT