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.


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 3333http://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_LIMITEDretryAfterMs), 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/coremcp/cli) и затем npm i ./webvector-0.1.0.tgz там, либо npm link.

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

Каждый тип провайдера — это небольшой интерфейс в packages/core/src/types.tsSearchProvider, 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

-
license - not tested
-
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
Release cycle
1Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Web research for agents: quality-scored Google search, webpage extraction, and deep research.

  • LLM-ready web search + instant answers + URL-to-clean-text fetch for agents and RAG.

  • The best web search for your AI Agent

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rthomas24/web-vector'

If you have feedback or need assistance with the MCP directory API, please join our Discord server