WebVector MCP Server
WebVector
Дайте вашему ИИ-агенту настоящий веб-поиск одним вызовом инструмента: поиск → чтение полных страниц → ранжирование → цитируемые отрывки.
Поисковые инструменты передают модели заголовки и сниппеты по 150 символов, поэтому она додумывает остальное. Инструменты загрузки передают ей 40 КБ навигации и шаблонного кода, и она тонет. WebVector выполняет всю работу посередине: запускает поиск, загружает и очищает каждый результат (HTML, PDF, Markdown), разбивает его на отрывки, ранжирует эти отрывки по отношению к вопросу — семантически, когда доступна модель эмбеддингов, лексически (BM25), когда нет — и возвращает только те отрывки, которые отвечают на запрос, каждый со своим URL, заголовком, смещениями и оценкой.
Работает без API-ключей и без загрузки моделей: DuckDuckGo + BM25, установка ~12 МБ.
Подключайте любой поисковый бэкенд, провайдера эмбеддингов, векторное хранилище или реранкер (или напишите свой в одном файле).
Поставляется как библиотека, MCP-сервер (Claude Code, Claude Desktop, Cursor, Windsurf, …) и CLI.
Вежливый и безопасный по умолчанию: robots.txt, ограничение частоты запросов на хост, защита от SSRF, лимиты размера/редиректов/времени, без телеметрии.
npx -y webvector-cli search "what changed in the MCP spec in 2026?"# Web research: what changed in the MCP spec in 2026?
**[1]** Streamable HTTP — Model Context Protocol — <https://modelcontextprotocol.io/specification/2026-07-28/…> (score 1.00)
> ### Earlier Streamable HTTP Revisions
> Protocol versions 2025-03-26 through 2025-11-25 also used the Streamable HTTP transport, but in a
> different shape: servers could assign a session via the Mcp-Session-Id header … None of these
> mechanisms are part of this revision.
…
## Sources
- Streamable HTTP — Model Context Protocol — <https://…> [1]Оглавление
Требования: Node.js ≥ 22.12 (рекомендуется Node 24). macOS, Linux и Windows.
Related MCP server: MyWebSearch MCP
1. Попробуйте за 30 секунд
Без установки, без ключей:
npx -y webvector-cli search "how does reciprocal rank fusion work" --statsВы увидите отрывки, а затем строку статистики вроде search duckduckgo 957ms · pages 4/5 908ms · embed 0 chunks (none/bm25) · retrieve 10ms · total 1879ms. embed … none/bm25 означает, что вы в лексическом режиме (см. §5) — семантический режим включается автоматически, как только появляется среда выполнения модели или API-ключ для эмбеддингов.
Проверьте, что будет использовать ваша машина:
npx -y webvector-cli doctor2. Использование в качестве MCP-сервера
MCP-сервер предоставляет четыре инструмента — web_research (основной), web_fetch, web_search, webvector_status — любому MCP-клиенту.
Claude Code
claude mcp add webvector -- npx -y webvector-mcpClaude Desktop / Cursor / Windsurf / VS Code — добавьте в ваш MCP-конфиг (claude_desktop_config.json, ~/.cursor/mcp.json, …):
{
"mcpServers": {
"webvector": {
"command": "npx",
"args": ["-y", "webvector-mcp"],
"env": { "BRAVE_API_KEY": "optional — see §7" }
}
}
}Это лексический уровень. Для семантического поиска на устройстве установите рядом среду выполнения модели:
"args": ["-y", "-p", "@huggingface/transformers", "-p", "webvector-mcp", "webvector-mcp"]…или просто поместите ключ эмбеддингов в env (OPENAI_API_KEY, VOYAGE_API_KEY, GEMINI_API_KEY, COHERE_API_KEY) — и он обновится сам.
По HTTP (для агентных фреймворков): npx -y webvector-mcp --http --port 3333 → http://127.0.0.1:3333/mcp (Streamable HTTP, только localhost). Добавьте --token <secret> (или WEBVECTOR_MCP_TOKEN), чтобы требовать Authorization: Bearer <secret>; привязка к любому другому адресу требует --host 0.0.0.0 --allow-remote --token … и должна находиться за TLS/собственной аутентификацией. GET /health для проверки живости.
Каждый результат web_research возвращается и в виде компактного Markdown (для модели), и в виде structuredContent (для вашего приложения), с уведомлениями о ходе выполнения во время работы.
3. Использование в качестве библиотеки
npm i webvectorimport { WebVector } from 'webvector';
const wv = new WebVector(); // zero-config
const res = await wv.research('what is reciprocal rank fusion');
console.log(res.markdown); // ready to drop into a prompt
for (const p of res.passages) console.log(p.score, p.citation); // "[1] Title — https://…"
await wv.close();Настройка через передаваемые параметры (полный список см. в §6):
const wv = new WebVector({
search: { provider: 'brave' }, // reads BRAVE_API_KEY
embeddings: { provider: 'openai', model: 'text-embedding-3-small' },
retrieval: { topK: 8, rerank: 'cohere' },
store: { mode: 'session' }, // reuse pages across calls
});
const res = await wv.research('How does Node 24 handle AbortSignal.any?', {
relatedQueries: ['AbortSignal.any example'], // extra angles (also searched)
freshness: 'year', // day | week | month | year
domainsAllow: ['nodejs.org', 'developer.mozilla.org'],
sessionId: 'conversation-42', // pages already read this session are reused
onProgress: (p) => console.error(p.stage, p.message),
});Другие вызовы: wv.search(query) (только результаты), wv.fetch(url) (одна страница → Markdown), wv.fetchAndRetrieve(url, query) (одна страница → релевантные отрывки), wv.listSessions(), wv.clearSession(id).
Передайте его модели как инструмент — привязки для популярных SDK находятся в одном импорте:
// Vercel AI SDK
import { generateText, isStepCount } from 'ai';
import { webVectorTools } from 'webvector/ai-sdk';
await generateText({ model, tools: await webVectorTools(wv), stopWhen: isStepCount(5), prompt });
// Anthropic Messages API // OpenAI Responses API // LangChain.js
import { anthropicTools, runAnthropicTool } from 'webvector/anthropic';
import { openaiTools, runOpenAITool } from 'webvector/openai';
import { langchainTools } from 'webvector/langchain';
// Anything else: plain JSON Schema
import { webResearchToolDefinition } from 'webvector';Рабочие версии каждого примера находятся в examples/.
4. Использование из командной строки
npm i -g webvector-cli # or keep using npx -y webvector-cli …
webvector search "query" [-k 8] [-p 12] [--provider brave] [--embeddings openai] [--rerank local] [--json|--md] [--stats]
webvector fetch <url> [--query "…"] # one page as Markdown, or just the passages relevant to --query
webvector serp "query" # search results only
webvector doctor [--live] # config, dependencies, provider connectivity, active tier
webvector init # writes webvector.config.yaml + .env.example
webvector config # print resolved config (secrets redacted)
webvector providers # every provider and the env var it reads
webvector mcp [--http] # run the MCP server5. Два уровня: лексический и семантический
Одна ручка — embeddings.provider, по умолчанию auto — определяет, как ранжируются отрывки:
Уровень | Установка | Ранжирование | Выбирается, когда |
Лексический ( | ~12 МБ, без загрузок | BM25 по всем загруженным страницам + расширение запроса + разнообразие по источникам | Нет среды выполнения модели и нет ключа эмбеддингов (обычный путь |
Семантический ( | + | Гибрид: векторы + BM25, объединённые через RRF, разнообразие MMR, опциональный реранкер | Автоматически, как только доступно что-либо из этого |
Обновитесь в любой момент: npm i @huggingface/transformers рядом с пакетом или задайте ключ. webvector doctor показывает, какой уровень активен. Лексический режим — это поддерживаемый режим, а не запасной: результаты помечаются как stats.embed.provider: 'none' и не считаются «ухудшенными».
6. Конфигурация
Приоритет: код → файл конфигурации → переменные окружения → значения по умолчанию. Файлы конфигурации: webvector.config.{ts,js,mjs,json,yaml,yml}, .webvectorrc или ключ webvector в package.json; поиск выполняется подъёмом от рабочего каталога. ${VAR} / ${VAR:-default} внутри значений заполняются из окружения.
webvector init создаёт заготовку с комментариями; вот параметры, которые люди действительно меняют:
search:
provider: duckduckgo # duckduckgo | brave | serper | serpapi | google-cse | searxng | tavily | tavily-keyless | exa | perplexity | wikipedia
fallbackProviders: [tavily-keyless, wikipedia]
resultsPerQuery: 10
embeddings:
provider: auto # auto | none | local | openai | openai-compatible | gemini | voyage | cohere | mistral | jina | ollama
model: Xenova/all-MiniLM-L6-v2 # local aliases: minilm (fast) | granite (quality) | embeddinggemma (best) | bge-small | nomic …
store:
provider: memory # memory | chroma | qdrant | pgvector
mode: ephemeral # ephemeral (per call) | session (reuse by sessionId, TTL) | persistent (external store)
retrieval:
topK: 12
hybrid: true # BM25 + vectors fused with RRF (semantic tier)
queryExpansion: true # heuristic (no LLM); pass retrieval.llm in code for LLM multi-query
maxPerSource: 3
mmr: true
rerank: false # local | cohere | voyage | jina | llm
ingestion:
maxPages: 10
maxConcurrentFetches: 8
timeoutMs: 15000
totalDeadlineMs: 45000
respectRobotsTxt: true
chunkSize: 480 # tokens
output:
markdown: true
maxPassageChars: 1500
logging:
level: warnЭквиваленты в переменных окружения: WEBVECTOR_SEARCH_PROVIDER, WEBVECTOR_EMBEDDINGS_PROVIDER, WEBVECTOR_EMBEDDINGS_MODEL, WEBVECTOR_STORE_PROVIDER, WEBVECTOR_STORE_MODE, WEBVECTOR_TOP_K, WEBVECTOR_MAX_PAGES, WEBVECTOR_LOG_LEVEL, WEBVECTOR_MODEL_CACHE, а также ключи провайдеров ниже. Каждая опция со значением по умолчанию: docs/CONFIGURATION.md.
7. Провайдеры
Задайте переменную окружения, укажите провайдера — готово. Подробности и подводные камни по каждому провайдеру: docs/PROVIDERS.md.
Поиск | env | Эмбеддинги | env | Хранилища / Реранкеры | env |
| — |
| — |
| — |
|
|
| — |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| реранк | — |
|
|
|
| реранк |
|
|
|
|
| реранк |
|
|
|
|
| реранк |
|
| — | любая модель Vercel AI SDK | — | реранк | — |
Если основной поисковый провайдер выходит из строя или срабатывает ограничение частоты запросов, автоматически перебирается цепочка fallbackProviders, и каждая попытка записывается в stats.search.attempts.
8. Что вы получаете в ответ
interface ResearchResult {
query: string; queries: string[]; // the query + expansions actually used
passages: Passage[]; // ranked; each: text, url, title, score (0–1), cosine?, bm25?,
// rerankScore?, chunkIndex, startOffset, endOffset, publishedAt?,
// fetchedAt, matchedQueries, citation "[n] Title — url"
sources: SourceSummary[]; // one per page: status ok|failed|cached, chunks, bestScore, passageIndices, failure?
failures: Failure[]; // per-URL / per-stage problems with machine codes (never thrown)
stats: { search, ingest, embed, retrieve, totalMs, warnings }; // timings + counts per stage
markdown?: string; // the pre-rendered version above
degraded?: 'search_only' | 'partial'; // e.g. every fetch failed → search snippets returned instead
}9. Ошибки и сбои
Два вида, намеренно разделённых:
Сбои происходят на уровне страницы и никогда не прерывают выполнение:
FETCH_TIMEOUT,FETCH_HTTP_ERROR,FETCH_BLOCKED_ROBOTS,FETCH_BLOCKED_SSRF,FETCH_TOO_LARGE,TOO_MANY_REDIRECTS,UNSUPPORTED_CONTENT_TYPE,PARSE_EMPTY,PARSE_FAILED. Они попадают вresult.failures[]иsources[].failure. Если все страницы завершились сбоем, вы всё равно получаете поисковые сниппеты (degraded: 'search_only',ALL_FETCHES_FAILED).Ошибки выбрасываются как
WebVectorErrorс полямиcode,message,remediation,retryable,provider,stageиtoJSON(); секреты маскируются. Примеры:MISSING_API_KEY(«Задайте BRAVE_API_KEY … или используйте провайдера без ключа: duckduckgo»),MISSING_DEPENDENCY(«npm i @huggingface/transformers — или embeddings.provider: 'none'»),SEARCH_BLOCKED,PROVIDER_RATE_LIMITED(сretryAfterMs),EMBEDDING_DIMENSION_MISMATCH(называет обе модели; предлагаетstore.clear()или новую коллекцию),INVALID_CONFIG.
10. Безопасность и этикет
WebVector загружает URL-адреса, выбранные поисковой системой, — то есть контент, на который может влиять злоумышленник, — поэтому загрузчик по умолчанию защищён:
Защита SSRF: цели в приватных, loopback, link-local, CGNAT, multicast, зарезервированных диапазонах, IPv4-mapped-IPv6 и
localhost/*.internalотклоняются; ответы DNS проверяются и каждый переход редиректа перепроверяется. Отключить можно только для доверенных локальных конфигураций (ingestion.allowPrivateNetworks).Лимиты на редиректы (5), размер ответа (5 МБ), время запроса (15 с) и общий дедлайн всего запуска (45 с); ограниченная конкурентность глобально и на каждый хост.
Этикет: соблюдается robots.txt (включая
Crawl-delay), идентифицируемый User-Agent, минимальный интервал между запросами к хосту, учитываетсяRetry-After.Разбор без исполнения: HTML разбирается с помощью linkedom (без скриптов и загрузки подресурсов), PDF — с помощью pdf.js в режиме no-eval; вызывающий код всегда получает только Markdown/простой текст с вырезанными управляющими символами.
Секреты: читаются из окружения/конфигурации, никогда не попадают в логи; маскируются в ошибках, в
webvector configи в MCP-инструментеwebvector_status. На диск ничего не записывается, если вы не включите каталог кэша страниц.Никакой телеметрии. Вообще.
MCP over HTTP привязывается только к
127.0.0.1, проверяетHost/Origin(защита от DNS-rebind), поддерживает bearer token и отказывается привязываться к другому адресу без--allow-remoteи токена.DNS-rebinding закрывается при подключении: проверка SSRF выполняется внутри DNS-запроса, используемого для открытия сокета, поэтому проверяется именно тот адрес, к которому происходит подключение.
Примечание про DuckDuckGo: провайдер без ключа обращается к публичным HTML-эндпойнтам DuckDuckGo с браузероподобным User-Agent (официальный API отсутствует). Этот провайдер по своей сути ограничен по частоте и хрупок; при интенсивном или коммерческом использовании стоит перейти на провайдера с ключом (
brave,serper,tavily). Загрузка страниц всегда использует честный User-AgentWebVector/….
Нашли что-то? Пожалуйста, откройте приватный security advisory на GitHub, а не публичный issue.
11. Запуск из исходников (локальная разработка)
git clone https://github.com/rthomas24/web-vector
cd webvector
npm install # installs all workspaces (~1 min; includes the optional model runtime for tests)
npm run build # tsdown → packages/*/dist
# use the local build
node packages/cli/dist/cli.js search "reciprocal rank fusion" --stats
node packages/mcp/dist/bin.js # MCP server on stdio
node packages/mcp/dist/bin.js --http --port 3333 # …or HTTP
# point an MCP client at the local build
claude mcp add webvector-dev -- node /absolute/path/to/webvector/packages/mcp/dist/bin.js
# quality gates
npm test # unit tests, offline (mocked HTTP), ~5 s
npm run test:live # real network + local model + MCP stdio round-trip (~20 s)
npm run lint # biome
npm run typecheck # TypeScript 7Структура репозитория и куда добавлять код: docs/ARCHITECTURE.md.
Чтобы использовать локальную сборку в другом проекте без публикации: выполните npm pack в packages/core (и mcp/cli) и затем npm i ./webvector-0.1.0.tgz там, либо npm link.
12. Создание собственного адаптера
Каждый тип провайдера — это небольшой интерфейс в packages/core/src/types.ts — SearchProvider, EmbeddingProvider, VectorStore, ContentParser, Reranker. Реализуйте его, а затем либо передайте экземпляр в конфигурации, либо зарегистрируйте имя, чтобы файлы конфигурации могли использовать его:
import { customSearchProvider, registerSearchProvider, WebVector } from 'webvector';
const myIndex = customSearchProvider('my-index', async (query) => [
{ url: 'https://…', title: '…', snippet: '…' },
]);
new WebVector({ search: { instance: myIndex } });
// or: registerSearchProvider('my-index', (opts) => new MyProvider(opts)); → search.provider: my-indexwebvector/testing экспортирует конформные проверки (searchProviderConformance, embeddingProviderConformance, vectorStoreConformance), которые можно подключить в любой тестовый раннер.
13. Как это работает
research(query)
1. search provider chain (DuckDuckGo → fallbacks) → dedupe by canonical URL → domain filters → top N
2. ingest concurrent, polite fetch → HTML (Readability→Markdown) | PDF | text → page cache
3. chunk+embed markdown-aware recursive chunks with heading breadcrumbs → content-hash dedupe → embed (batched, cached)
4. retrieve query + expansions → vector top-k lists + BM25 top-k lists → weighted RRF → cosine cutoffs
→ near-duplicate removal → per-source cap → MMR → optional rerank → top-k
5. format passages with citations, sources, failures, per-stage stats, MarkdownТипичный запуск на ноутбуке: поиск ~1 с, 8 страниц загружены и разобраны ~1–2,5 с, извлечение < 50 мс → ~2 с лексический (lexical) / ~4 с семантический (semantic).
14. Дорожная карта
Хранилища LanceDB и Pinecone * адаптер headless-браузера для страниц, отрисованных JS-омлекционное извлечение (с обобщённым LLM контекстом фрагментов) как опциональная функция * отдельный бинарный файл без требования к установленному Node * Python-пакет, распространяющий фикстуры конформ- проверок.
Лицензия
MIT © Ryan Thomas
This server cannot be deployed
Maintenance
Related MCP Connectors
Scrape, crawl and search the web for AI agents via MCP.
Live AI-native web search with citations. One tool for every MCP client. Flat per-request pricing.
Web search, fetch, extract, and research for AI agents. Markdown output + AI-synthesized answers.
Web search, scraping, RAG answers with citations, and translation as MCP tools.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to perform grounded web research with injection resistance, claim verification, and cost-aware routing through MCP tools like web_search, fetch_url, extract_claims, and check_grounding.MIT
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to perform unified web research through a single MCP server, including search, page fetching, recursive crawling, document parsing, YouTube transcript extraction, and deep multi-query research.3-
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to perform live web searches across 9 engines, scrape web pages into clean formats, and run agentic research with citations via MCP.98 PyPI3MIT
- AlicenseBqualityBmaintenanceEnables AI agents to perform web searches and extract full-text content from web pages via standard MCP tools, with fallback search and semantic reranking.22MIT