Gemini Research Mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Gemini Research Mcp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
MCP server for AI-powered research using Gemini. Fast grounded search, URL extraction, comprehensive Deep Research, and session management.
Built on FastMCP `4.1` with the modern sessionless MCP protocol, Gemini `4 Argon` for web research and follow-ups (3.8 Flash for helpers), MCP Tasks (SEP-1732), the guard-pattern elicitation flow, a BM25-compacted tool catalog, and pluggable Disk/Redis storage with a zero-configuration local default.

<details> <summary>Mermaid source</summary>
flowchart TB
subgraph Client["MCP Client"]
Claude["Claude / Copilot"]
end
subgraph Server["gemini-research-mcp"]
direction TB
FastMCP["FastMCP 4 Server<br/>@mcp.tool()<br/>BM25SearchTransform"]
subgraph Tools["Tools"]
RW["research_web<br/>Grounded lookup"]
RD["research_deep<br/>Autonomous 3-20min"]
RF["research_followup<br/>Continue session"]
RR["resume_research<br/>Recover interrupted"]
FW["fetch_webpage<br/>Content extraction"]
EX["export_research_session<br/>MD/JSON/DOCX"]
LS["list_research_sessions"]
LT["list_format_templates"]
end
subgraph Modules["Core Modules"]
Quick["quick.py<br/>Web grounding"]
Deep["deep.py<br/>Deep research agent"]
Content["content.py<br/>SSRF protection"]
StorageMod["storage.py<br/>Session + artifact store"]
Templates["templates.py<br/>Format templates"]
end
end
subgraph External["External Services"]
Gemini["Google Gemini API"]
Web["Web Sources<br/>via trafilatura"]
end
subgraph Storage["Persistence"]
Disk["DiskStore<br/>XDG data directory"]
Redis["Redis/Valkey<br/>shared multi-worker storage"]
end
Claude -->|"MCP Protocol"| FastMCP
FastMCP --> Tools
RW --> Quick
RD --> Deep
RF --> StorageMod
RR --> StorageMod
FW --> Content
LT --> Templates
Quick -->|"grounding"| Gemini
Deep -->|"agentic"| Gemini
Content -->|"httpx"| Web
StorageMod --> Disk
StorageMod -.-> Redis</details>
The server exposes a BM25-compacted catalog: only the 7 tools below plus the synthetic search_tools/call_tool pair are listed by default (fastmcp.server.transforms.search.BM25SearchTransform). Utility tools (fetch_webpage, research_followup, list_research_sessions, list_format_templates, refine_research_plan, inspect_mcp_server_for_gemini, list_research_engines, list_research_runs, get_research_run, export_research_bundle) are hidden from the default listing to keep the catalog small for LLM tool-selection, but remain fully callable directly by name or via the call_tool proxy, and are discoverable by relevance through search_tools.
| Tool | Description | Latency | Visible by default |
|---|---|---|---|
research_web | Web search with citations | varies | ✅ |
research_deep | Multi-step autonomous research (MCP Tasks) | 3-20 min | ✅ |
research_deep_max | Maximum-comprehensiveness Deep Research for exhaustive/high-stakes work | longer-running | ✅ |
research_run | Engine-neutral research job (MCP Tasks): Gemini by default, optional local engine | engine-dependent | ✅ |
research_compare | Run exactly two engines on one query and return attributed reports (no synthesis) | engine-dependent | ✅ |
resume_research | Resume interrupted/in-progress sessions | instant | ✅ |
export_research_session | Disk-first export to persistent Markdown, JSON, or DOCX artifacts | instant | ✅ |
search_tools | Discover hidden utility tools by relevance (BM25) | instant | ✅ |
call_tool | Proxy to invoke any hidden tool by name | varies | ✅ |
research_followup | Continue conversation after research | varies | discoverable |
list_research_sessions | List saved research sessions | instant | discoverable |
list_format_templates | Browse report format templates | instant | discoverable |
refine_research_plan | Iterate on or approve a collaborative_planning=True plan | instant-3min | discoverable |
fetch_webpage | Extract article content from a specific URL (SSRF-protected, chunkable) | 0.5-2 sec | discoverable |
inspect_mcp_server_for_gemini | Inspect remote MCP reachability and schemas (diagnostic only) | varies | discoverable |
list_research_engines | Engines, backends, models and availability (configuration only, no provider call) | instant | discoverable |
list_research_runs | Metadata of your research jobs and comparisons (limit 1-100) | instant | discoverable |
get_research_run | Read one run by run_id; refresh=true re-polls a native provider job | instant | discoverable |
export_research_bundle | Attributed JSON/Markdown bundle of a run, with no model or search call | instant | discoverable |
research_deep / research_deep_max Deep Research parameters| Parameter | Type | Default | Description | |
|---|---|---|---|---|
visualization | "off" \ | "auto" | "off" | Let the agent produce and persist supporting images/charts. Images are persisted as MCP resource artifacts (research://exports/{id}), never inlined as text. |
collaborative_planning | boolean | false | Return the drafted research plan and an interaction ID instead of running the full report. Approve or iterate on the plan with `refine_research_plan(previous_interaction_id=..., decision="approve" | "iterate")`. |
mcp_servers | array \ | null | null | Disabled. Any non-empty value fails before network or Gemini API access because provider-side Deep Research remote MCP is not reliable. |
fetch_webpage Parametersfetch_webpage is discoverable through search_tools in the default server listing.
The fetch_webpage tool supports chunked reading for large pages and optional proxy routing:
| Parameter | Type | Default | Description | |
|---|---|---|---|---|
url | string | required | HTTP/HTTPS URL to fetch | |
max_length | integer \ | null | null | Maximum characters to return (chunk size) |
start_index | integer | 0 | Character offset for pagination | |
proxy_url | string \ | null | null | Optional HTTP(S) proxy URL for the request |
Notes:
robots.txt is checked before fetch when protego is installed.start_index.proxy_url is omitted, the server falls back to FETCH_PROXY_URL when set.proxy_url must be a public HTTP(S) host (private/internal proxy hosts are blocked).Install the web extra for the highest-quality fetch_webpage experience:
pip install 'gemini-research-mcp[web]'
# or
uv add 'gemini-research-mcp[web]'Without [web], fetch_webpage still works using the built-in HTML fallback, but trafilatura extraction and protego-based robots.txt checks are unavailable.
Key insight: Gemini Deep Research runs asynchronously on Google's servers. Even if VS Code disconnects, your research continues. The resume_research tool retrieves completed work.research_deep asks clarifying questions for vague queries. On the modern sessionless MCP protocol this uses a stateless guard pattern (InputRequiredResult, two independent tool calls, no server-held connection); legacy handshake clients still use MCP Elicitation (ctx.elicit())research_deep_max exposes Google's Max agent for exhaustive, high-stakes, and offline research workflowsresearch_deep(..., collaborative_planning=True) returns the drafted plan for approval before running the full report; refine or approve it with refine_research_planvisualization="auto" lets Deep Research produce supporting images, persisted as downloadable MCP resource artifactsfile_search_store_namesmcp_servers before network/provider access until Google exposes a reliable structured result contractlangchain.mcp.MCPAdapter (LangChain 1.4.0a2) over both stdio and streamable-http - see scripts/langchain_interop_smoke.py. LangChain is never a dependency of this package.pip install gemini-research-mcp
# or
uv add gemini-research-mcpDownload the .mcpb bundle from GitHub Releases and open it in Claude Desktop for single-click installation.
The bundle uses UV runtime - dependencies are installed automatically, no Python required.
research_run and research_compare are engine-neutral jobs. They require MCP Tasks, return a normalized result envelope ({"result": <text>, "schema_version": 1, "run": {...}}), and keep the legacy research_deep/resume_research/export_research_session tools working.
| Engine | Backend | Notes |
|---|---|---|
gemini (default) | gemini-native | Gemini Deep Research; recoverable by provider interaction ID |
gemini_max | gemini-native | Gemini Deep Research Max |
local_deep_research | local-deep-research | Optional, operator-installed Local Deep Research bridge; see below |
research_compare takes exactly two distinct engines and runs both. It returns each engine's report, attributed and verbatim; it never merges or synthesizes them. Synthesis is the caller's job. One engine failing yields a partial result that keeps the other report. Comparing two Gemini profiles can incur two paid research workloads.
Three IDs are never interchangeable:
submission and may create a second paid job (the same logical request is not deduplicated across Tasks; there are no caller idempotency keys).
job_…, cmp_…): stable, derived from the owner and Task. Use itwith get_research_run, export_research_bundle and list_research_runs.
jobs never expose a provider ID. Provider IDs are not accepted as run IDs.
queued, running, completed, failed, cancelled,interrupted, expired; a comparison can also be partial. interrupted means the server cannot prove an outcome.
GEMINI_RESEARCH_TTL_SECONDS) set atcreation; updates and refreshes never extend it. Expired runs read expired. A submission is refused (RETENTION_TOO_SHORT) when the TTL cannot cover the engine timeout plus a cleanup margin.
have been sent but before its ID was stored, the run reads interrupted with SUBMISSION_UNKNOWN. It is not resubmitted automatically; the provider job may still exist and be billed.
get_research_run(refresh=true) or the legacy resume_research. While this process still executes the job, resume_research answers busy.
restart it is reported interrupted; it is never resumed or re-run.
and local storage. With GEMINI_RESEARCH_STORAGE_URL (Redis) or a non-memory FASTMCP_DOCKET_URL, submissions are refused with DISTRIBUTED_SUBMISSION_UNSUPPORTED rather than risk duplicate paid jobs after a redelivery or a new runner. Read tools still work.
Runs, their linked sessions, images and bundles are owned by the authenticated principal. Another principal sees "not found". Over streamable-http the job tools require an authenticated principal (AUTH_REQUIRED otherwise); stdio has a single local owner. Historical sessions with no job link stay visible as before. The local engine is not offered over HTTP unless the operator sets GEMINI_RESEARCH_LDR_ALLOW_HTTP=true (LOCAL_ENGINE_HTTP_DISABLED otherwise).
The Gemini API does not let a model continue an interaction that belongs to a Deep Research agent. research_followup therefore answers from the report stored in the session, treated as untrusted context, in a stateless model call.
The bridge targets an operator-installed ldr-mcp pinned to LDR commit 362d65652156732b08a704f0d3faa77996b4f0de (stdio only). This server installs and starts nothing: set GEMINI_RESEARCH_LDR_COMMAND to its absolute path and configure the LDR_* values in .env.example (Ollama on loopback plus an explicit search backend). The engine stays unavailable until all are set, and the Gemini-only default never spawns a child process.
Ollama, but the configured search backend receives queries over the network, and local compute costs time and hardware.
child process is not sandboxed. LDR's configuration is verified before any query is sent.
paid or networked workload.
or its relevance filter drops every result (observed with Wikipedia and a 4B model). The bundle then lists no sources for that engine; the report is still kept verbatim and untrusted.
export_research_bundle(run_id, format="json"|"markdown") renders a run (single or comparison) from stored data with no model, search or provider call. Each engine entry carries engine, backend, model, status, recovery state, warnings, error, sources, usage and its report, labelled verbatim and untrusted. Bundles are saved to the export directory and as an owner-scoped research://exports/{id} artifact.
| Variable | Required | Default | Description |
|---|---|---|---|
GEMINI_API_KEY | Yes | — | Google AI Studio API key |
GEMINI_MODEL | No | gemini-4-argon | Shared model for research_web and research_followup |
GEMINI_SUMMARY_MODEL | No | gemini-3.8-flash | Model for session metadata, titles, and semantic session matching (thinking level low) |
DEEP_RESEARCH_AGENT | No | deep-research-preview-04-2026 | Default agent for research_deep; accepts fast, standard, deep-research, max, deep-research-max, or exact agent IDs |
FETCH_PROXY_URL | No | — | Default HTTP(S) proxy for fetch_webpage |
GEMINI_RESEARCH_STORAGE_URL | No | — | redis://... URL to share sessions, exports, and (unless overridden) Tasks across multiple instances/workers. Local DiskStore + memory Tasks remain the default |
FASTMCP_DOCKET_URL | No | — | Advanced Tasks backend override. Takes priority over GEMINI_RESEARCH_STORAGE_URL; unset preserves memory Tasks locally |
GEMINI_RESEARCH_STORAGE_PATH | No | XDG data dir | Custom directory for the local DiskStore |
GEMINI_RESEARCH_TTL_SECONDS | No | backend default | Override session/export TTL |
GEMINI_RESEARCH_EXPORT_DIR | No | ~/.gemini-research/exports/ | Disk-first destination when export_research_session has no output_path |
GEMINI_RESEARCH_LDR_COMMAND | No | — | Absolute path of an operator-installed ldr-mcp; enables the optional local_deep_research engine (see Research jobs and engines) |
GEMINI_RESEARCH_LDR_ALLOW_HTTP | No | false | Operator opt-in to offer the local engine over streamable-http |
GEMINI_RESEARCH_TRANSPORT | No | stdio | stdio (default, historical) or streamable-http (opt-in, see Transports) |
GEMINI_RESEARCH_HTTP_HOST | No | 127.0.0.1 | Bind host for streamable-http. Non-loopback requires GEMINI_RESEARCH_HTTP_BEARER_TOKEN |
GEMINI_RESEARCH_HTTP_PORT | No | 8000 | Bind port for streamable-http |
GEMINI_RESEARCH_HTTP_PATH | No | /mcp | URL path for streamable-http |
GEMINI_RESEARCH_HTTP_BEARER_TOKEN | No | — | Static bearer token required to call streamable-http. Never reuse GEMINI_API_KEY for this |
The default Gemini 4 Argon model requires paid-tier API access. To use the previous Flash model for web research and follow-ups, explicitly set GEMINI_MODEL=gemini-3.8-flash in the server environment. The server does not silently fall back to another model.
Query clarification uses fixed gemini-3.8-flash; it is not controlled by GEMINI_SUMMARY_MODEL. Web research preserves HIGH thinking. Latency varies with the query and provider load; neither web research nor follow-ups have a fixed completion-time guarantee.
cp .env.example .env
# Edit .env with your API keyThe server defaults to stdio, matching every existing VS Code/Claude Desktop configuration - no changes required for local, single-client use.
Streamable HTTP is opt-in, for remote or multi-client/multi-worker deployments, and is sessionless (no sticky session required across calls):
# Local-only (no auth required, loopback binding):
uv run gemini-research-mcp --transport streamable-http
# Remote-accessible (bearer token required - refuses to start otherwise):
GEMINI_RESEARCH_HTTP_BEARER_TOKEN=$(openssl rand -hex 32) \
uv run gemini-research-mcp --transport streamable-http --host 0.0.0.0 --port 8000Binding to any non-loopback host (0.0.0.0, ::, a LAN/public IP, etc.) without GEMINI_RESEARCH_HTTP_BEARER_TOKEN set causes the server to refuse to start - this prevents accidentally exposing your Gemini API quota to the public internet. 127.0.0.1/localhost/::1 never require a token.
--transport, --host, --port, and --path CLI flags mirror the GEMINI_RESEARCH_TRANSPORT/GEMINI_RESEARCH_HTTP_HOST/GEMINI_RESEARCH_HTTP_PORT/GEMINI_RESEARCH_HTTP_PATH environment variables (CLI flags take precedence).
Research sessions and export artifacts are stored through a single backend-agnostic layer:
DiskStoreunder the XDG data directory, while FastMCP Tasks use in-process memory (GEMINI_RESEARCH_STORAGE_PATH to override) - zero configuration, single process/single machine.
GEMINI_RESEARCH_STORAGE_URL=redis://host:6379/0to share sessions, exports, and Tasks across multiple server instances or workers. Set FASTMCP_DOCKET_URL only when Tasks must use a different backend. Requires the distributed extra:
uv add 'gemini-research-mcp[distributed]'Google exposes Deep Research variants through the Gemini Interactions API agent field, not the regular Gemini model field:
research_deep uses deep-research-preview-04-2026 by default. Use it forinteractive research, comparisons, investigations, and latency/cost-sensitive synthesis.
research_deep_max uses deep-research-max-preview-04-2026. Use it when theuser explicitly asks for Max, exhaustive/comprehensive due diligence, market maps, literature reviews, board-ready reports, offline/nightly research, or maximum completeness over speed.
For Copilot and other LLM clients, the two tools are intentionally separate so Max can be selected from the tool name and description. There is no public model parameter for Deep Research, because follow-up and quick research use Gemini models while Deep Research uses Interactions agents.
Disabled since `v0.16.0b2`. Any non-empty mcp_servers value is rejected for both research_deep and research_deep_max before remote inspection, network access, or Gemini API consumption.
The request shape is valid and Google documents MCP as a Deep Research tool, but repeated paid E2E runs completed without any mcp_server_tool_call/mcp_server_tool_result steps. One run also invented substitute evidence after failing to obtain the fixture data. See googleapis/python-genai#2126.
inspect_mcp_server_for_gemini remains available to inspect endpoint reachability, tool names, and schema compatibility. It does not enable the disabled Deep Research integration.
Remote MCP will only be reconsidered after an upstream correction and repeated E2E runs that retain non-empty structured tool-call and tool-result steps.
Add to .vscode/mcp.json:
{
"servers": {
"gemini-research": {
"command": "uvx",
"args": ["gemini-research-mcp"],
"env": {
"GEMINI_API_KEY": "your-api-key"
}
}
}
}Or run from source:
{
"servers": {
"gemini-research": {
"command": "uv",
"args": ["run", "--directory", "path/to/gemini-research-mcp", "gemini-research-mcp"],
"envFile": "${workspaceFolder}/path/to/gemini-research-mcp/.env"
}
}
}uv run gemini-research-mcp
# or
uvx gemini-research-mcpExport research sessions to professional Word documents with:
To enable DOCX export, install with the [docx] extra:
{
"servers": {
"gemini-research": {
"command": "uvx",
"args": ["--from", "gemini-research-mcp[docx]", "gemini-research-mcp"],
"env": {
"GEMINI_API_KEY": "your-api-key"
}
}
}
}export_research_session is disk-first: the file is always written to disk and the absolute path is returned on the first line of the response text (e.g. ✅ **Saved to:** /…/report.docx). This means any MCP client — GUI or headless — gets a usable file path back.
By default exports are written to GEMINI_RESEARCH_EXPORT_DIR (defaults to ~/.gemini-research/exports/; falls back to the system temp dir if that location isn't writable). Override per-call with the output_path argument:
{
"name": "export_research_session",
"arguments": {
"interaction_id": "v1_...",
"format": "docx",
"output_path": "/absolute/or/relative/path/report.docx"
}
}When output_path is supplied, the parent directory must already exist (no silent mkdir). GUI hosts (e.g. VS Code Copilot Chat) also receive an EmbeddedResource attachment backed by the persistent research://exports/{id} resource store for native "Save As" — clients that can't render it can safely ignore it.
research_deep requires MCP Tasks support (SEP-1732) on the client. Clients that do not advertise the tasks capability will receive a -32600 error.
Known client status:
github/copilot-cli#2538; until that lands, use research_web from the CLI.
# Install with DOCX support
pip install 'gemini-research-mcp[docx]'
# or
uv add 'gemini-research-mcp[docx]'| Feature | Description |
|---|---|
| Cover Page | Title, date, duration, tokens, AI agent |
| Clickable TOC | Internal hyperlinks navigate to sections |
| Syntax Highlighting | Pygments-powered code blocks with GitHub colors |
| Professional Styling | Calibri fonts, proper heading hierarchy (H1-H4) |
| Page Margins | Standard 1-inch (2.54cm) margins |
| Heading Spacing | keep_with_next prevents orphan headings |
| Sources | Full URLs as clickable hyperlinks |
| Pure Python | No external binaries (Pandoc not required) |
MCP Resources provide read-only data that clients can access:
| Resource | Description |
|---|---|
research://models | Available models and their capabilities |
research://exports | List cached exports ready for download |
research://exports/{id} | Download an exported file (Markdown, JSON, or DOCX) |
The export_research_session tool creates exports and returns a resource URI. Clients (like VS Code) can then fetch the resource to download the file with proper MIME type handling.
uv sync --extra dev
uv run pytest
uv run mypy src/
uv run ruff check src/Release numbering and gates are described in docs/versioning.md.
uv run pytest # Unit tests
uv run pytest -m e2e # E2E tests (requires GEMINI_API_KEY)
uv run pytest --cov=src/gemini_research_mcp # With coverage| Tool | Typical Cost |
|---|---|
research_web | ~$0.01-0.05 per query |
research_deep | ~$2-5 per task |
Deep Research uses ~80-160 searches and ~250k-900k tokens per task.
MIT
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.