Back to Browse

Footnote MCP Server

Developer ToolsUse Caution4.2MCP RegistryLocal
Free

Server data from the Official MCP Registry

Source-grounded web research: search, extraction, verification, and browser automation.

About

Source-grounded web research: search, extraction, verification, and browser automation.

Security Report

4.2
Use Caution4.2High Risk

footnote-mcp is a well-structured, feature-rich research assistant with proper authentication for hosted deployments and reasonable permission scoping for its purpose as a web research tool. The codebase demonstrates good security practices around API key handling and input validation. Minor code quality observations around broad exception handling and logging do not materially impact security posture. Supply chain analysis found 9 known vulnerabilities in dependencies (0 critical, 6 high severity). Package verification found 1 issue.

4 files analyzed · 14 issues found

Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.

Permissions Required

This plugin requests these system permissions. Most are normal for its category.

HTTP Network Access

Connects to external APIs or services over the internet.

network_websocket

Check that this permission is expected for this type of plugin.

File System Read

Reads files on your machine. Normal for tools that analyze or process local data.

File System Write

Writes or modifies files on your machine. Check that this is expected for the tool.

env_vars

Check that this permission is expected for this type of plugin.

process_spawn

Check that this permission is expected for this type of plugin.

system_info

Check that this permission is expected for this type of plugin.

How to Install

Add this to your MCP configuration file:

{
  "mcpServers": {
    "io-github-kazkozdev-footnote-mcp": {
      "args": [
        "footnote-mcp"
      ],
      "command": "uvx"
    }
  }
}

Documentation

View on GitHub

From the project's GitHub README.

footnote-mcp — web research MCP server with claim verification

Search, extract data, and verify every claim against the source page.

Add to Cursor · Claude Desktop setup

Runs without API keys · 45 tools · MIT licensed

Quick start

pip install footnote-mcp
python -m playwright install chromium   # browser tier for JS-heavy and blocked pages

footnote-mcp speaks MCP over stdio. Point a client at it — Claude Desktop's claude_desktop_config.json, or Cursor's ~/.cursor/mcp.json:

{"mcpServers": {"footnote": {"command": "footnote-mcp"}}}

No API keys are needed to start. Ask the client to run startup_health_check to see what this install can actually do (output trimmed):

{"ok": true, "checks": {
  "trafilatura": {"ok": true}, "playwright": {"ok": true}, "pdfplumber": {"ok": true},
  "tesseract_binary": {"ok": true, "path": "/opt/homebrew/bin/tesseract"},
  "cache_dir": {"ok": true, "path": "/Users/you/.footnote-mcp/source_cache"}}}

Search the web without configuring an API key

web_search queries the zero-key providers — Bing, DuckDuckGo, Brave, Wiby — alongside any keyed provider you configured, then deduplicates and merges them into one ranking. Each result records which engines returned it, so agreement across independent indexes is visible rather than assumed. Snippets count as discovery only; nothing here is evidence yet.

{
  "provider": "auto", "count": 2,
  "results": [{
    "title": "Almost every new car sold in Norway is electric - Our World in Data",
    "url": "https://ourworldindata.org/data-insights/almost-every-new-car-sold-in-norway-is-electric",
    "score": 1.444, "engines": ["brave", "ddg"]
  }]
}

Provider routing, keys, and semantic reranking: docs/search-backends.md.

Extract tables and files from a page into structured rows

web_extract_tables parses HTML tables into columns/rows carrying the source URL. web_detect_downloads, web_parse_file, and web_fetch_json cover the CSV/XLS/XLSX/PDF/JSON a page links instead of rendering. From a Wikipedia revenue table, max_rows: 3:

{
  "columns": ["Rank", "Name", "Industry", "Revenue (USD millions)", "Employees"],
  "rows": [{"Rank": "1", "Name": "Walmart", "Industry": "Retail",
            "Revenue (USD millions)": "680,985", "Employees": "2,100,000"}],
  "row_count": 3, "total_row_count": 100, "truncated": true
}

Verify that a source actually supports a claim

The part a plain search tool does not do. evidence_entailment compares a claim to the source text and returns a verdict; corroborate_claim triangulates across excerpts, and locate_claim_span returns the supporting sentence with character offsets.

Claim: "Norway's battery-electric share of new passenger cars was 82.4% in 2023." Source excerpt: "In 2023, battery-electric vehicles accounted for 82.4% of all new passenger cars registered in Norway, up from 79.3% in 2022."

{"status": "supported", "score": 0.778, "reason": "token overlap heuristic", "backend": "heuristic"}

heuristic is offline and deterministic; backend="ollama" adds a local LLM judge and auto escalates to it. Measured accuracy: benchmarks/REPORT.md.

How it works

Search snippets are discovery, never evidence. Discovery merges several independent indexes; fetching escalates through a ladder — plain HTTP, optional proxy, headless Chromium, optional hosted scrape API — and stops at the cheapest tier returning real content. Extraction pulls text, tables, and linked files, each cached with its source URL. Only then does verification run, checking the claim against the fetched text before it counts. web_deep_search wraps the whole loop: it decomposes requirements, re-searches unresolved gaps, and returns an evidence ledger with a funnel showing where candidates were lost.

query → merged discovery → fetch ladder → extract (text · tables · files) → verify vs source → evidence

Configuration

OptionDefaultWhat it does
--headedoffShow the Chromium window instead of running headless

Environment variables

All optional — the server starts and searches with none of them set.

VariableRequiredWhat it does
FOOTNOTE_SEARXNG_URLnoZero-key SearXNG instance, tried first by auto
TAVILY_API_KEY / BRAVE_API_KEYnoKeyed search providers, merged with the zero-key ones
GOOGLE_API_KEY + GOOGLE_CSE_IDnoGoogle Programmable Search provider
GITHUB_TOKENnoRaises the rate limit for github_search
FOOTNOTE_RESEARCH_MODELnoOllama model for web_deep_search planning and extraction
FOOTNOTE_EMBED_MODELnoEmbedding model for semantic: true (default bge-m3)
FOOTNOTE_BROWSER_FALLBACKno0 disables the Chromium tier (default 1)
FOOTNOTE_PROXIESnoComma-separated proxy URLs for the fetch ladder
FOOTNOTE_SCRAPE_APInofirecrawl or scrapingbee, with its matching key
FOOTNOTE_SOURCE_CACHEnoCache location (default ~/.footnote-mcp/source_cache/)

Every variable with its default: .env.example, docs/fetching.md.

Requirements

  • Python 3.10 or newer
  • Chromium via python -m playwright install chromium, for the browser tier and browser tools
  • Any MCP client speaking stdio; config is documented for Claude Desktop and Cursor
  • Optional: a local Ollama for semantic: true and the ollama entailment backend
  • Optional: the system tesseract binary for OCR in web_screenshot and scanned PDFs
  • No API keys, no account, no hosted service

Limitations

  • The offline entailment heuristic scores 100% on numeric and factual claims but 83% overall on the labelled set; purely semantic negation and paraphrase need backend="ollama".
  • CI runs Ubuntu with Python 3.12 only. macOS is the development platform; Windows is untested.
  • Zero-key providers are scraped, so results vary by IP, and Brave and DuckDuckGo enter a cooldown after rate limiting.
  • Semantic reranking is best-effort: with no Ollama reachable, the original ranking is returned unchanged.
  • Generated recipes run in a subprocess limited to six stdlib imports, with eval, exec, open, and __import__ rejected — a validator, not a hardened sandbox.
  • The hosted HTTP server holds per-user rate limits in memory; they reset on restart.

Docker

docker run -i --rm ghcr.io/kazkozdev/footnote-mcp:latest   # bundles Chromium and Tesseract
{"mcpServers": {"footnote": {"command": "docker",
  "args": ["run", "-i", "--rm", "ghcr.io/kazkozdev/footnote-mcp:latest"]}}}

uvx / pipx / from source

uvx footnote-mcp
pipx install footnote-mcp
python3 -m venv .venv && source .venv/bin/activate && pip install -e .

OCR and local NLI

pytesseract needs the system binary (brew install tesseract). evidence_entailment with backend="local_nli" needs pip install -r requirements-nli.txt and FOOTNOTE_NLI_MODEL.

Tests

python -m pytest -q                              # offline; no network or keys
RUN_LIVE_WEB_TESTS=1 python -m pytest -m live    # opt-in live search

Claude Desktop Cursor

tests PyPI Python License

Issues · Tools · Search backends · Fetching · Hosting · Benchmarks · License · LinkedIn

Reviews

No reviews yet

Be the first to review this server!