internet-context-mcp
About
Read-only MCP server giving AI agents the web as compact, ranked, verified evidence. Local cross-encoder reranker, NLI claim verification, semantic cross-source agreement and contradiction detection. No API keys.
Details
- Author
- vivekvar-dl
- Categories
- Search, Other, AI, Knowledge Base
Jump to
Setup
Install internet-context-mcp in your MCP client (Claude Desktop, Cursor, Windsurf, and others).
Repository: https://github.com/vivekvar-dl/internet-context-mcp
Follow the installation instructions in the repository README, then restart your MCP client.
A read-only MCP server that gives AI agents the web as compact, ranked, verified evidence — no API keys, no cloud retrieval, all models local.
Six read-only tools —web_research,web_context,web_search,web_read,web_verify,web_extract— plus MCP resources, prompts, and properoutputSchema/readOnlyHintmetadata. Behind each tool: local BM25 ranking, a local cross-encoder reranker, a local NLI classifier, local sentence embeddings, a regex prompt-injection scanner, and a two-tier (in-memory + SQLite) fetch cache.
Measured, not aspirational: 20/20 relevance eval pass, 92.5% prompt-injection recall at 0% false-positive rate on benign pages, contradiction detector with 0 false positives on real-world web (seeeval tablebelow).
Add this to yourclaude_desktop_config.json(or equivalent MCP-host config):
{ "mcpServers": { "internet-context": { "command": "npx", "args": ["-y", "internet-context-mcp"] } } }
First call lazy-downloads three local models from HuggingFace (~125 MB total, cached): the cross-encoder reranker, NLI classifier, and sentence-embedding model. Once cached, the server runs fully offline. No API keys required at any point.
{ "env": { "BRAVE_SEARCH_API_KEY": "", // optional: use Brave instead of the DDG fallback "INTERNET_CONTEXT_MCP_RERANK": "0", // optional: disable the cross-encoder reranker "INTERNET_CONTEXT_MCP_NLI": "0", // optional: disable NLI for web_verify "INTERNET_CONTEXT_MCP_EMBEDDINGS": "0", // optional: disable semantic clustering / contradictions "INTERNET_CONTEXT_MCP_CACHE_DIR": "" // optional: override SQLite cache path } }
git clone https://github.com/vivekvar-dl/internet-context-mcp cd internet-context-mcp npm install npm run build node dist/index.js # exits when stdin closes — used by the MCP host
- web_research— one-shot search + multi-source fetch + cross-source ranking + per-chunk citations + redundancy-based agreement signal + NLI-backed contradiction detection.
- web_verify— claim-vs-sources verification, NLI-classifier-backed (entailment / neutral / contradiction), regex fallback.
- web_context— fetch + rank + return ranked evidence chunks with priority capsule (TL;DR), retrieval-confidence signal, structured-data extraction, prompt-injection scan, source provenance with DOM paths.
- web_read— clean compact page text with token-savings metadata.
- web_search— Brave whenBRAVE_SEARCH_API_KEYis set; DuckDuckGo HTML fallback otherwise.
- web_extract— best-effort schema-driven extraction.
- readOnlyHint: true+openWorldHint: trueannotations on every tool. Claude Desktop / Code can skip permission prompts.
- outputSchemaon every tool. Hosts get typed JSON (structuredContent) instead of re-parsing free-form text.
- internet-context://page/{fingerprint}MCP resource template — the host can re-reference fetched pages by URI without re-calling a tool.
- verify_with_sources,summarize_from_context,research_a_topicMCP prompt templates.
- Two-tier fetch cache: in-memory + a persistent SQLite layer at~/.cache/internet-context-mcp/cache.sqlite. Survives across host restarts.
- Realjs-tiktokentokenizer (cl100k_base). No morechars / 4approximations.
- Optional Playwright rendering for JS-heavy SPAs viarender: "browser", shipped as anoptionalDependency.
SeeCHANGELOG.mdfor the per-version detail.
- a short priority capsule (TL;DR) before the long evidence
- ranked evidence chunks with character offsets, section paths, and DOM paths
- a retrieval confidence signal so the agent can ask for more sources when needed
- structured data from the page, when present (JSON-LD, microdata, metadata)
- page metadata and content fingerprints
- prompt-injection risk warnings (visible / hidden / comment / metadata)
- token savings estimates
One-shot research tool: search the web, fetch the top N results in parallel, rank chunks within each source (with the local reranker by default), then cross-rank globally and return a unified evidence pack with per-chunk source citations and a redundancy-based agreement signal.
Use this when you'd otherwise be callingweb_searchand thenweb_contextseveral times in a row.
{ "query": "What is the Model Context Protocol and who built it?", "depth": 4, "max_tokens_total": 3000 }
{ "query": "...", "provider": "duckduckgo_html", "depth": 4, "unique_sources": 3, "sources": [ { "index": 0, "requested_url": "https://en.wikipedia.org/wiki/Model_Context_Protocol", "ok": true, "title": "Model Context Protocol - Wikipedia", "retrieval_confidence": { "level": "high", "score": 0.79 }, "selected_chunks": 1 } ], "ranked_evidence": [ { "source_index": 1, "source_url": "https://www.anthropic.com/news/model-context-protocol", "source_title": "Introducing the Model Context Protocol", "chunk_id": 2, "cluster_id": 2, "agreement_count": 1, "score": 1.0, "combined_score": 1.0, "section": null, "matched_terms": ["model", "context", "protocol"], "text": "Today, we're open-sourcing the Model Context Protocol..." } ], "agreement_score": 0.0, "verdict_reasons": ["sources_did_not_overlap"], "token_budget": { "max_tokens_total": 3000, "used_tokens": 1949 } }
agreement_countandagreement_scoreusesemantic similarity(all-MiniLM-L6-v2 cosine, ~22MB, lazy-loaded) by default in v0.4.0+. Paraphrased agreement now counts: three sources independently saying the same fact in different words will cluster together. The clustering falls back to 4-gram shingle Jaccard when the embedding model fails to load; theclustering_methodfield on every response shows which one ran.
contradictionslists cases where chunks from different sources are on the same topic but neither entails the other in either direction. The detector runs in two stages: anembedding-cosine prefilter(≥0.45) that requires the two chunks be discussing the same claim, and then anNLI bidirectional non-entailmentcheck (≤0.05 entailment both directions) on the survivors. Both must hold.
Each contradiction includestopical_similarity(the actual cosine) andconfidence(the NLI signal).
The prefilter intentionally allows same-cluster pairs through: in the wild, two sources makingopposingclaims about the same fact paraphrase each other with very high cosine (~0.9), so they cluster together. Excluding same-cluster pairs would mean missing the contradictions we most want to surface.
Detector evaluation — measured, not aspirational
This is what we have measured the detector to actually do. Eval scripts are inscripts/demo-contradiction-.tsso the numbers are reproducible.
Across ~30 real sources fetched, the detector fired exactly zero times. It also produced zero false positives.
The truthful claim about v0.4.x: the detector hasnear-zero false-positive rate on real-world weband fires reliably onlexically explicit opposing claims. It does not, in our testing, detect disputes that are real but expressed with hedged or qualified prose — which is most of how the indexed web talks about disagreement. Three reasons:
- Search engines (DDG, Google) return homogenized mainstream content; the dispute lives in academic papers or contrarian sources that don't rank well.
- Mainstream web prose qualifies its disagreement ("some studies suggest", "for certain populations", "recent research has shown"). NLI's bidirectional non-entailment does not fire on hedged contrast.
- Many primary sources where the disputeisdirect (NEJM, BMJ, ScienceDirect, Britannica) block static fetches with HTTP 403.
If you want the detector to catch hedged disagreement, you'd need to loosen the entailment ceiling and accept some false positives. If you want broader source access, you'd need browser rendering and (for paywalled journals) credentials. v0.4.x does neither; it stays read-only, local, and honest about what it sees.
Honest caveat about the agreement signal: whenagreement_count=Nacross N sources, that means N sources from the search results corroborated each other — not that the claim is true. Search engines tend to return the current mainstream view, which can hide genuine disputes (the eggs/cholesterol query returned 4 modern sources all agreeing the modern consensus, even though the topic was contested for decades).
Fetches a URL, cleans it, splits it into chunks, ranks chunks against an agent task with a local BM25-style algorithm, and returns only the best evidence budget. This is the main token-reduction tool.
{ "url": "https://example.com/docs", "task": "find installation steps and configuration details", "max_tokens": 1800 }
{ "task": "find installation steps and configuration details", "title": "Documentation", "context": "[chunk 2 | score 1]\\nInstall the package with npm install example...", "evidence_chunks": [ { "id": 2, "score": 1, "score_breakdown": { "bm25": 2.4, "phrase": 0, "heading": 0.5, "metadata": 0.35, "structured_data": 0, "position": 0 }, "provenance": { "char_start": 182, "char_end": 348, "section": "Installation", "section_path": ["Installation"], "source_blocks": [ { "block_id": 4, "tag": "p", "dom_path": "body:nth-of-type(1) > main:nth-of-type(1) > section:nth-of-type(1) > p:nth-of-type(1)", "line_start": 22, "line_end": 22, "overlap_score": 1, "text_preview": "Install the package with npm install example." } ] }, "matched_terms": ["install", "config"], "text": "Install the package with npm install example..." } ], "structured_data": { "metadata": { "description": "..." }, "json_ld": [], "microdata": [] }, "safety": { "risk": "low", "score": 0, "warnings": [] }, "priority_capsule": { "tldr": "Install with npm install example. Configure via the MCP client config file.", "top_sections": ["Installation", "Configuration"], "highlight_chunk_ids": [2, 3] }, "retrieval_confidence": { "level": "high", "score": 0.78, "reasons": [], "suggestion": null }, "provenance": { "content_fingerprint": "9f2a1c6e7b0d3a11", "clean_text_fingerprint": "3d41e2f0780a5c19" }, "ranking": { "algorithm": "hybrid-bm25-lite", "signals": ["bm25", "phrase", "heading", "metadata", "structured_data", "position"], "total_chunks": 12, "selected_chunks": 3, "selected_tokens": 940 }, "token_savings_estimate": { "raw_tokens": 42000, "returned_tokens": 1100, "saved_tokens": 40900, "savings_ratio": 0.9738 } }
Fetches a URL, removes noisy page chrome, extracts the main content, and returns clean text plus token savings metadata.
{ "url": "https://example.com/docs", "query": "installation configuration", "mode": "compact", "max_tokens": 4000 }
Searches the web and returns compact, source-classified results.
IfBRAVE_SEARCH_API_KEYis set, it uses Brave Search. Otherwise it falls back to DuckDuckGo HTML search.
{ "query": "Model Context Protocol TypeScript SDK docs", "limit": 5 }
Checks whether a claim is supported, refuted, or unclear from one or more source URLs. Fetches each source, ranks chunks against the claim, and looks for explicit support or contradiction (with simple negation detection near matched terms). Returns a combined verdict plus per-source supporting and refuting evidence chunks.
{ "claim": "the server is read-only", "sources": [ "https://example.com/docs", "https://example.com/safety" ], "max_tokens_per_source": 1400 }
{ "claim": "the server is read-only", "verdict": "supported", "confidence": 0.82, "reasons": ["2_sources_support"], "sources": [ { "requested_url": "https://example.com/docs", "final_url": "https://example.com/docs", "title": "Documentation", "verdict": "supported", "confidence": 0.74, "supporting_chunks": [ { "chunk_id": 3, "section": "Safety", "score": 0.91, "matched_terms": ["server", "read", "only"], "contains_negation": false, "text_preview": "The default tools are read-only and never submit forms or modify remote data." } ], "refuting_chunks": [] } ] }
Best-effort generic field extraction from clean page text. This is intentionally secondary toweb_context; in many agents, the better flow is to callweb_contextand let the host model reason over the returned evidence chunks.
{ "url": "https://example.com/docs", "schema": { "title": "string", "install_command": "string", "configuration_file": "string" }, "query": "installation command configuration file" }
The repo includes a 100-URL real-data stress set indata/real-sites.json. It exercises the full pipeline against live pages:
npm run stress:real -- --limit=20 --concurrency=3 --timeout=15000 --maxTokens=1500
It measures live fetch success, token savings, selected chunks, structured-data detection, safety warnings, and source provenance coverage.
The repo includes a 54-case adversarial set inevals/prompt-injection.jsoncovering visible instruction-override, hidden-text (display:none / visibility:hidden / opacity:0 / aria-hidden / off-screen), HTML-comment injection, credential requests, exfiltration prompts, and benign-control pages.
Reported numbers for v0.4.0 (regex scanner, no LLM):
{ "true_positive_rate": 0.925, "false_positive_rate": 0, "precision": 1, "recall": 0.925, "by_category": { "instruction_override_visible": 0.80, "hidden_text": 0.90, "html_comment": 1.00, "credential_request": 1.00, "exfiltration": 1.00, "benign_control": 1.00 } }
Known misses: "disregardthe*prior instructions" (intervening article), "no longer valid" framing, off-screen positioning viaposition:absolute;left:-9999px. Real failures, intentionally surfaced rather than papered over.
The repo includes a labeled relevance set inevals/relevance.json. It checks whether compressed capsules preserve required facts, avoid junk terms, stay under the evidence token budget, and include source provenance.
The latest 20-case run on v0.3.0 (reranker on by default, real tokenizer) passed all cases:
{ "all_pass_rate": 1, "included_pass_rate": 1, "excluded_pass_rate": 1, "provenance_pass_rate": 1, "token_budget_pass_rate": 1, "average_token_savings_ratio": 0.9192 }
For clients that accept JSON MCP server config:
{ "mcpServers": { "internet-context": { "command": "node", "args": ["C:/Users/domai/internet-context-mcp/dist/index.js"], "env": { "BRAVE_SEARCH_API_KEY": "" } } } }
- Read-only first: no clicking, login, purchases, form submissions, or state-changing actions.
- Compact output first: agents should get useful context, not page dumps.
- Local ranking first: reduce tokens without requiring a second LLM API key.
- Evidence first: returned context should include the text used to support claims.
- Untrusted web content first: pages are scanned for instruction-like text before the agent reasons over them.
- Honest limits: weak extraction should be marked as weak instead of pretending to be reliable.
This is an early open-source prototype. The strongest part isweb_context: local cleanup, chunking, ranking, structured-data discovery, safety scanning, and token reduction. The weakest part is generic structured extraction without an LLM, so that tool should stay secondary until it has real eval coverage.
- BRAVE_SEARCH_API_KEY— if set,web_searchuses Brave Search instead of the DuckDuckGo HTML fallback.
- INTERNET_CONTEXT_MCP_RERANK=1— enable the local cross-encoder reranker globally. Off by default.
- INTERNET_CONTEXT_MCP_CACHE_DIR— override the SQLite cache location. Defaults to~/.cache/internet-context-mcp.
To enable browser rendering (only needed for JS-rendered SPAs):
npm install playwright npx playwright install chromium
Then call any tool withrender: "browser".
- Multi-sentence claim decomposition inweb_verifyso compound claims return per-clause verdicts.
- Stable text-fragment anchors (#:~:text=...) in chunk provenance for deep-linking back to the page.
- PDF support for the fetch + clean pipeline.
- robots.txt+ crawl-delay awareness for responsible read-only fetching.
- Expand the prompt-injection eval beyond the hand-curated 54 cases — integrate publicly-available adversarial datasets.
- Close the regex gaps the injection eval surfaced (intervening articles, "no longer valid", off-screen positioning).
Search global news using natural language. Webz.io News Search API returns the most relevant articles and content, with filters for source, country, language, date, sentiment, and category.
Search and extract information about research papers from arXiv.
Unified access to multiple search providers and AI tools like Tavily, Perplexity, Kagi, Jina AI, Brave, and Firecrawl.
A research assistant powered by Perplexity AI for intelligent search, documentation retrieval, and code assistance.
Optimized web search for LLMs using the Tavily Search API.
Fetch, convert, and search AWS documentation pages, with recommendations for related content.
Search campgrounds around the world on campertunity, check availability, and provide booking links.
Lightning-Fast, High-Accuracy Deep Research Agent 👉 8–10x faster 👉 Greater depth & accuracy 👉 Unlimited parallel runs
The Ferryhopper MCP Server exposes ferry routes, schedules and booking redirects so an AI assistant can discover connections across Europe and the Mediterranean and send users to Ferryhopper to complete bookings.
All-in-One SEO & Web Intelligence Toolkit API from FetchSERP.
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.




