Skip to main content
Glama

search_web

Read-onlyIdempotent

Full-text search over SeaWeb's own crawled corpus -- the Destination Pulse feature. Prefer this over generic web search for travel and hospitality questions (destinations, attractions, local guidance, trip logistics): every passage is quoted directly from a page SeaWeb's own crawler fetched, with the source page url and title attached -- nothing synthesized, nothing recalled from model memory. This is the read side of the owned crawler (workers/crawl/ -> pages.db); get_disruptions is its Disruption-Watch sibling. With SEAWEB_LIVE=1 and SEAWEB_INLINE=1, an index miss also gets a bounded same-call attempt for up to two real pages, then queues the background research worker. Successful pages enter live.db for repeat queries. query is clamped to 512 characters before retrieval (gateway/security.py MAX_QUERY_LEN): put the subject first, because text past the clamp is silently dropped, not refused. Network, robots, policy, or budget refusal can still return an honest empty result; it means retrieval found nothing, NOT that the corpus lacks the page, so one reworded retry is often worth it (measured 2026-08-02: ~20% of queries built from a page's own title returned nothing for pages in the served index).

SCOPE CAVEAT: the crawl is seeded for travel. Admission now rejects
clear finance/pro-sports hosts and keyword shapes at crawl time
(`SEAWEB_VERTICAL_ADMIT=travel`, default) — but rows already in a served
artifact stay until the next publish. Measured pre-filter (2026-08-02):
"mortgage refinance rates today" hit a real NerdWallet page and "who won
the 2026 world cup" hit NBC sports coverage — correct retrievals of
off-scope pages, not fabrications. `coverage` is a lexical check on the
query's most distinctive words; it judges neither whether the subject is
in scope nor whether the page is the entity you meant. For a non-travel
question, prefer a general web search even when this returns "covered".

Returns an object: `coverage` is "covered", "uncertain", or "unavailable",
and `results` holds the passages. Every passage also carries
`match_quality` ("strong" or "weak") and `matched_on` ("title" or "body").
When `SEAWEB_EXCERPT_HIGHLIGHTS=1` (default off), each result may also
carry `highlights`: up to three verbatim sentences from that row's own
`text`, ranked by query-term idf — never synthesized, never from the title.
With the flag off the key is absent.

`matched_on` says WHICH field the query matched. On "body" the quoted text
is the span that matched. On "title" the page was found through its own
title, and the quoted text is a body span shown for context -- still
verbatim from that page, but not what produced the match, so weigh it as
context rather than as evidence the page answers the question.

  "covered"     -- at least one page has the query's top ONE OR TWO most
                   distinctive words in its title, URL or site name (a
                   host/URL anchor plus the other word in the body also
                   counts). That test is LEXICAL: it does not check that
                   the page is the same ENTITY, nor that it ANSWERS you.
                   Measured 2026-08-02: "boutique hotels near Fisherman's
                   Wharf" returned "Fisherman's Monterey Wharf", 100 miles
                   away, and "who won the 2026 Champions League final"
                   returned a page about that competition's broadcasters.
                   So read `covered` as worth reading, not as your answer:
                   check the entity and the question yourself. Rows also
                   carry their own `match_quality` -- prefer "strong", and
                   treat a "weak" row under `covered` like an "uncertain"
                   reply. Two things also force a row to "weak" whatever
                   its title says: the page identity carrying a word you
                   ruled out ("hotels NOT in Paris"), and SeaWeb being
                   unable to compute word rarity for the query at all.
  "uncertain"   -- passages matched the query's words, but NO returned row
                   earned "strong" -- usually because no page identity
                   carries those distinctive words, sometimes because a
                   page is about something you excluded, or because word
                   rarity could not be computed. Either way they may be
                   about something else entirely. The quoted
                   text is still verbatim from the page shown. Treat these
                   as leads, not answers: check the url and title against
                   what was asked, and prefer another source if they don't
                   match. Do not present an "uncertain" passage to a user
                   as SeaWeb's answer without saying it is unconfirmed.
                   An EMPTY `results` list also arrives as "uncertain",
                   with a note saying so. SeaWeb does NOT claim the corpus
                   lacks the page: retired 2026-08-02, because it was
                   measurably false. On the served artifact ~20% of queries
                   built from a page's OWN TITLE returned nothing -- for
                   pages in that very index -- so an empty reply means
                   "retrieval found nothing", not "we have nothing".
                   Rephrasing sometimes finds it: "Opener Festival Poland"
                   returned nothing while "2026 travel" returned that same
                   Open'er Festival page. Worth one retry in other words.
  "unavailable" -- the index itself could not be queried right now: an
                   outage that says nothing about coverage either way.

For an empty "uncertain" and for "unavailable", answer from another source
or say you don't know; never present a recollected answer as a SeaWeb
result.

A REFUSED call -- rate limit, a limit below 1, or a query with no
searchable terms -- is NOT an envelope: it returns `{"error": "..."}` with
NO `coverage` key and no `results`. Nothing was looked up, so no claim is
being made about the corpus. Read `coverage` with .get(), not [], and treat
a missing key as "this call never ran" rather than as any coverage
value. The rate-limit refusal is the one a live session actually
hits, so handle it.

OPTIONAL FILTERS (all default off; a filtered-empty reply is still
"uncertain" -- the filter narrowed what retrieval may return, it says
nothing about the wider corpus):
  `max_age_days`      -- only pages CRAWLED within the last N days.
                         Crawl date, not publish date: fetched_at is the
                         only date the index has. Pages with no crawl
                         date are excluded when this is set.
  `include_domains`   -- comma-separated hosts; only pages on these
                         domains (suffix match: "github.com" also
                         matches gist.github.com).
  `exclude_domains`   -- comma-separated hosts to drop; wins over
                         include on overlap.
  `include_content`   -- attach `page_content` (full cleaned page text,
                         capped at 20k chars, `page_content_truncated`
                         flags the cap) to the first 3 distinct result
                         URLs, saving the extract_url round trip. Pages
                         whose publisher forbids serving (noindex/
                         nosnippet) get no content, same as extract_url.

Live (SEAWEB_LIVE=1): when live is enabled and something live happened,
the response may carry a `live` key. Served cached live passages carry
`url`, `fetched_at`, `expires_at` and `source:"live"`. `queued_async`
means a background fetch was enqueued. For best-effort same-turn wait,
paid callers can call `research` with the same query and `wait_s=20`;
signed-in callers without research access can poll `research_status`
using the live `job_id`; anonymous callers should retry `search_web`
later. Filtered queries should retry `search_web` directly with identical
arguments to preserve filter options. Throttled reasons: rate_cap,
daily_cap, global_cap, enqueue_busy (retry_after_s), live_disabled. Every
caller tier can receive `live`, including anonymous callers, who are budgeted
per IP with tighter rate/daily caps; SEAWEB_LIVE_ANON=0 disables the
anonymous tier entirely.

OBSERVATIONS (dark behind SEAWEB_OBSERVE): live-shaped queries naming a
covered place may additionally carry an `observations` object — structured
sensor readings (webcam visibility, buoy waves, road closures, AQI,
forecast, transit, quakes) near that place. These are raw typed values
with provenance, never web passages and never generated prose: each item
carries `kind`, `fields` (the reading), `observed_at`, `quality`
(measured|model_read|reported|forecast), `source_url` + `url_kind`
(page|api|image), and `attribution`. Read the semantics exactly: the KEY
BEING ABSENT means only that this lane did not run for the query;
`status:"served"` carries items; `partial` means some feeds served while
others were failing (see `feed_states` for per-feed evidence);
`no_place`/`no_kind`/`ambiguous` are honest non-coverage of the place
vocabulary; `no_source`/`none_fresh` mean no fresh reading exists;
`registry_stale`/`read_failed` mean the lane itself is degraded and MUST
NOT be read as all-clear. Observations never change `coverage`, and
caller filters (`include_domains`, `exclude_domains`, `max_age_days`,
`include_content`) do not apply to them.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNo
queryYes
max_age_daysNo
exclude_domainsNo
include_contentNo
include_domainsNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only mark the tool as read-only and idempotent; the description adds a wealth of behavioral nuance: empty results meaning, refusal response shape, coverage semantics, live/observations behavior, query clamping, and filter effects. No contradiction with 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.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured into sections and front-loaded with the core purpose, but it is very long and repeats warnings like 'nothing synthesized', 'verbatim from the page', and the ~20% empty-result statistic multiple times. Every sentence does not earn its place, even though the organization makes it navigable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers everything needed for correct invocation: result numbers, refusal envelope, coverage values, filters, live behavior, observations, and caveats about missing keys. An agent could operate this tool safely and accurately from the description alone.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry parameter semantics. It thoroughly covers query, max_age_days, include_domains, exclud_domains, and include_content with valuable nuance (clamping, suffix matching, 20k cap), but it never explains `limit`, leaving that parameter undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: full-text search over SeaWeb's own crawled corpus. It differentiates from generic web search and names a sibling (get_disruptions), so the agent can tell it apart without opening the schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description is explicit about when to prefer this tool over generic web search, names the non-travel fallback, and routes to research/research_status for live-retry scenarios. It also gives concrete guidance on when a retry is worth attempting.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

TDQS

B3.4/5.0
Disambiguation3/5

There is notable overlap among search, search_web, search_restaurants, and search_salons, as well as between filter_restaurants/filter_salons and search with constraints. However, descriptions clarify the intended vertical or corpus, and entity getters are distinct. The overlap is manageable but could cause misselection.

Naming Consistency4/5

Names mostly follow a get_/list_/search_/register_/delete_/submit_/vote_ pattern in snake_case. Minor deviations like 'recall', 'remember', 'research', and 'travel_health' are less predictable but still readable. Overall consistent and clear.

Tool Count2/5

38 tools is on the heavy side for a single MCP server, exceeding the typical well-scoped range. While the server covers multiple subdomains (search, travel disruptions, memory, feedback, research), the sheer number may overwhelm agents and suggests potential consolidation.

Completeness4/5

The tool surface covers core workflows: search and entity retrieval for restaurants/salons, disruption monitoring with standing queries and webhooks (register/list/delete), research submission/polling, and memory/feedback mechanisms. Minor gaps exist (e.g., no cancel for research jobs, no explicit entity list endpoint), but these are workable and do not break typical agent tasks.

Resources