Skip to main content
Glama
rthomas24

WebVector MCP Server

by rthomas24

WebVector

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

한 번의 도구 호출로 AI 에이전트에 실제 웹 리서치를 제공하세요: 검색 → 전체 페이지 읽기 → 순위 지정 → 인용된 구절.

검색 도구는 모델에게 제목과 150자 분량의 스니펫만 넘겨주므로, 모델은 나머지를 추측해야 합니다. 가져오기(fetch) 도구는 40KB 분량의 내비게이션과 상용구를 넘겨주므로, 모델은 그 속에서 파묻힙니다. WebVector는 그 중간의 모든 작업을 처리합니다: 검색 실행, 모든 결과(HTML, PDF, Markdown) 다운로드 및 정리, 구절로 분할, 질문에 대한 구절 순위 지정 — 임베딩 모델이 있으면 의미론적으로, 없으면 어휘적으로(BM25) — 그리고 쿼리에 답하는 구절만 각각의 URL, 제목, 오프셋, 점수와 함께 반환합니다.

  • API 키와 모델 다운로드 없이 작동합니다: DuckDuckGo + BM25, ~12 MB 설치.

  • 모든 검색 백엔드, 임베딩 제공자, 벡터 스토어 또는 리랭커를 연결할 수 있습니다(또는 한 파일로 직접 작성).

  • 라이브러리, 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. 두 가지 계층: 어휘 vs 의미론

  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용 바인딩은 import 한 번이면 됩니다:

// 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. 두 가지 계층: 어휘 vs 의미론

embeddings.provider(기본값 auto)라는 단 하나의 설정이 구절 순위 지정 방식을 결정합니다:

계층

설치

순위 지정 방식

선택되는 조건

어휘(none)

~12 MB, 다운로드 없음

가져온 전체 페이지 대상 BM25 + 쿼리 확장 + 소스별 다양성

모델 런타임과 임베딩 키가 모두 없는 경우(일반 npx 경로)

의미론(local, openai, …)

+ @huggingface/transformers(~230 MB, 모델 23 MB, 완전 오프라인) 또는 임의의 임베딩 API 키

하이브리드: RRF로 융합된 벡터 + BM25, MMR 다양성, 선택적 리랭커

둘 중 하나라도 사용 가능하면 자동으로

언제든 업그레이드할 수 있습니다: 패키지와 함께 npm i @huggingface/transformers를 설치하거나 키를 설정하세요. webvector doctor는 현재 활성화된 계층을 표시합니다. 어휘 모드는 폴백이 아니라 지원되는 모드입니다 — 결과는 stats.embed.provider: 'none'으로 표시되며 "저하된" 상태가 아닙니다.

6. 설정

우선순위: 코드설정 파일환경 변수기본값. 설정 파일(webvector.config.{ts,js,mjs,json,yaml,yml}, .webvectorrc, 또는 package.jsonwebvector 키)은 작업 디렉터리에서 위로 거슬러 올라가며 찾습니다. 값 안의 ${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

rerank local

exa

EXA_API_KEY

voyage

VOYAGE_API_KEY

rerank cohere

COHERE_API_KEY

perplexity

PERPLEXITY_API_KEY

cohere

COHERE_API_KEY

rerank voyage

VOYAGE_API_KEY

searxng(자체 호스팅)

SEARXNG_URL

mistral / jina / ollama

MISTRAL_API_KEY / JINA_API_KEY / OLLAMA_HOST

rerank jina

JINA_API_KEY

wikipedia

모든 Vercel AI SDK 모델

rerank 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. 오류와 실패

두 가지 종류를 의도적으로 구분합니다:

  • 실패(Failures)는 페이지별로 발생하며 실행을 중단하지 않습니다: 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).

  • 오류(Errors)는 WebVectorError로 던져지며 code, message, remediation, retryable, provider, stage, toJSON()을 포함합니다. 비밀 값은 마스킹됩니다. 예시: MISSING_API_KEY("BRAVE_API_KEY를 설정하세요 … 또는 키가 필요 없는 제공자를 사용하세요: duckduckgo"), MISSING_DEPENDENCY("npm i @huggingface/transformers — 또는 embeddings.provider: 'none'"), `SE

  • SSRF 가드: private, loopback, link-local, CGNAT, multicast, reserved, IPv4-mapped-IPv6 및 localhost/*.internal 대상은 거부됩니다. DNS 응답을 확인하고 모든 리디렉션 홉을 다시 확인합니다. 신뢰할 수 있는 로컬 설정(ingestion.allowPrivateNetworks)에서만 선택 해제할 수 있습니다.

  • 상한: 리디렉션(5회), 응답 크기(5MB), 요청당 시간(15초), 전체 실행 마감(45초)이 있으며, 전역 및 호스트별 동시성에 제한이 있습니다.

  • 예의: robots.txt를 준수하고(Crawl-delay 포함), 식별 가능한 User-Agent를 사용하며, 호스트별 최소 간격을 지키고, Retry-After를 존중합니다.

  • 실행 없는 파싱: HTML은 linkedom으로 파싱되고(스크립트나 하위 리소스 로딩 없음), PDF는 no-eval 모드의 pdf.js로 파싱됩니다. 호출자는 제어 문자가 제거된 Markdown/일반 텍스트만 받습니다.

  • 비밀: 환경/설정에서 읽으며, 로그에 기록하지 않고, 오류, webvector config, MCP webvector_status 도구에서 모두 삭제됩니다. 페이지 캐시 디렉터리를 활성화하지 않는 한 디스크에 아무것도 기록하지 않습니다.

  • 원격 측정 없음, 절대.

  • HTTP를 통한 MCP127.0.0.1에만 바인딩하고, Host/Origin을 검증하며(DNS 리바인딩 보호), 베어러 토큰을 지원하고, --allow-remote 토큰 없이는 다른 곳에 바인딩을 거부합니다.

  • DNS 리바인딩은 연결 시점에 차단됩니다: SSRF 검사는 소켓을 여는 데 사용되는 DNS 조회 내에서 실행되므로, 검사된 주소는 실제로 연결되는 주소입니다.

  • DuckDuckGo 참고: 키 없는 공급자는 브라우저와 유사한 User-Agent로 DuckDuckGo의 공개 HTML 엔드포인트와 통신합니다(공식 API는 없음). 본질적으로 속도 제한이 있고 취약합니다. 대규모 또는 상업적 사용은 키 기반 공급자(brave, serper, tavily)로 전환해야 합니다. 페이지 가져오기는 항상 정직한 WebVector/… User-Agent를 사용합니다.

문제를 발견하셨나요? 공개 이슈 대신 GitHub에서 비공개 보안 권고를 열어 주세요.

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.

로컬 빌드를 다른 프로젝트에서 게시 없이 사용하려면: packages/core(및 mcp/cli)에서 npm pack을 실행하고 해당 프로젝트에서 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초, 검색 < 50ms → ~2초 어휘 / ~4초 의미론적.

14. 로드맵

LanceDB 및 Pinecone 저장소 · 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