Skip to main content
Glama
rthomas24

WebVector MCP Server

by rthomas24

WebVector

npm: webvector npm: webvector-mcp npm: webvector-cli CI License: MIT

Дайте вашему ИИ-агенту настоящий веб-поиск одним вызовом инструмента: поиск → чтение полных страниц → ранжирование → цитируемые отрывки.

Поисковые инструменты передают модели заголовки и сниппеты по 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]

Оглавление

  1. Попробуйте за 30 секунд

  2. Использование в качестве MCP-сервера (Claude Code, Claude Desktop, Cursor…)

  3. Использование в качестве библиотеки

  4. Использование из командной строки

  5. Два уровня: лексический и семантический

  6. Конфигурация

  7. Провайдеры

  8. Что вы получаете в ответ

  9. Ошибки и сбои

  10. Безопасность и этикет

  11. Запуск из исходников (локальная разработка)

  12. Создание собственного адаптера

  13. Как это работает

  14. Дорожная карта · Лицензия

Требования: 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 doctor

2. Использование в качестве MCP-сервера

MCP-сервер предоставляет четыре инструмента — web_research (основной), web_fetch, web_search, webvector_status — любому MCP-клиенту.

Claude Code

claude mcp add webvector -- npx -y webvector-mcp

Claude 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 webvector
import { 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 server

5. Два уровня: лексический и семантический

Одна ручка — embeddings.provider, по умолчанию auto — определяет, как ранжируются отрывки:

Уровень

Установка

Ранжирование

Выбирается, когда

Лексический (none)

~12 МБ, без загрузок

BM25 по всем загруженным страницам + расширение запроса + разнообразие по источникам

Нет среды выполнения модели и нет ключа эмбеддингов (обычный путь npx)

Семантический (local, openai, …)

+ @huggingface/transformers (~230 МБ, модель 23 МБ, полностью офлайн) или любой API-ключ эмбеддингов

Гибрид: векторы + 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

duckduckgo (по умолчанию)

—

none (BM25)

—

memory (по умолчанию)

—

brave

BRAVE_API_KEY

local (Transformers.js)

—

chroma

CHROMA_URL

serper (Google)

SERPER_API_KEY

openai

OPENAI_API_KEY

qdrant

QDRANT_URL

serpapi

SERPAPI_API_KEY

openai-compatible (LM Studio, vLLM, …)

OPENAI_COMPATIBLE_BASE_URL

pgvector

DATABASE_URL

tavily / tavily-keyless

TAVILY_API_KEY

gemini

GEMINI_API_KEY

реранк local

—

exa

EXA_API_KEY

voyage

VOYAGE_API_KEY

реранк cohere

COHERE_API_KEY

perplexity

PERPLEXITY_API_KEY

cohere

COHERE_API_KEY

реранк voyage

VOYAGE_API_KEY

searxng (самостоятельно размещённый)

SEARXNG_URL

mistral / jina / ollama

MISTRAL_API_KEY / JINA_API_KEY / OLLAMA_HOST

реранк jina

JINA_API_KEY

wikipedia

—

любая модель Vercel AI SDK

—

реранк llm (ваша функция)

—

Если основной поисковый провайдер выходит из строя или срабатывает ограничение частоты запросов, автоматически перебирается цепочка 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-Agent WebVector/….

Нашли что-то? Пожалуйста, откройте приватный 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-index

webvector/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

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables 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
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables 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
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables 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 PyPI
    3
    MIT
  • A
    license
    B
    quality
    B
    maintenance
    Enables AI agents to perform web searches and extract full-text content from web pages via standard MCP tools, with fallback search and semantic reranking.
    2
    2
    MIT