Percival Deep Research
Integrates DuckDuckGo as the default web search engine for research operations, providing fast raw snippet searches and multi-source web research capabilities without requiring an API key.
Utilizes OpenAI SDK transport architecture to connect with various LLM providers (Venice AI, MiniMax, OpenRouter) for research orchestration, requiring the 'openai:' prefix for model configuration regardless of the actual provider.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Percival Deep Researchdeep research on quantum computing advancements in 2024"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
🤖 Percival Deep Research - percival.OS MCP
Version 3.0.0
📋 Description
Percival Deep Research is a highly capable MCP server designed to equip the Nanobot agent with autonomous, deep-dive web research capabilities. It explores and validates numerous sources, focusing only on relevant, trusted, and up-to-date information.
This server is part of the percival.OS ecosystem, a Personal Agentic Operating System designed for autonomy, security, and absolute privacy.
v3.0 highlights — 48 bugs closed across 4 official bug-hunt rounds and 2 internal code-reviews; surface expanded to 5 tools + 1 resource template + 4 prompts. Same single-endpoint inference model as v2.2.x. See CHANGELOG.md for the full history.
Related MCP server: ToolCenter MCP
🛡️ percival.OS Principles
Like all components of percival.OS, this MCP server strictly follows our core principles:
Privacy & Governance: The entire research and synthesis process is governed by your API keys and local configurations.
Data Sovereignty: Knowledge extracted from the web is processed locally and integrated into your agent's context without external harvesting.
Hardened Security: We implement Defense-in-depth with strict input sanitization against prompt injection and isolation of untrusted web content.
Transparency: Based on the
GPT Researcherproject, but extensively refactored and hardened for the Percival ecosystem.
🚀 Surface (v3.0.0)
Tools (5)
Nome | Função | Assinatura | Latência | Notas |
| Pesquisa profunda multi-source |
| 30–120 s | Rate-limited; in-flight dedup; retorna |
| Raw snippets, sem LLM |
| 3–10 s | Rate-limited; sem synthesis |
| Contexto crudo wrappado |
| <1 s |
|
| Metadados das fontes wrappados |
| <1 s |
|
| Report Markdown final |
| 5–30 s | LLM-free se custom_prompt=None |
Resource (1)
research://{topic}— context direto (sem session). Percent-decode server-side.
Prompts (4) ✨ new in v3.0
Prompt | Quando usar |
| Workflow completo (deep + report) |
| Raw snippets sem síntese (atalho, sem LLM) |
| Re-formata research existente por audience (general / executive / technical / academic) |
| Triagem de erros via |
⚙️ Configuration in percival.OS (Nanobot)
Quickstart (v3.0.0 — recommended)
The server uses a single inference endpoint (one LLM). Same setup works for any OpenAI-compatible gateway (OpenAI, Venice, MiniMax, OpenRouter, local LLMs, etc.):
{
"mcpServers": {
"percival-deep-research": {
"command": "uv",
"args": ["run", "--no-sync", "percival-deep-research"],
"env": {
"PYTHONUNBUFFERED": "1",
"MCP_TRANSPORT": "stdio",
"INFERENCE_API_KEY": "YOUR_KEY",
"INFERENCE_BASE_URL": "https://api.minimax.io/v1",
"INFERENCE_LLM": "minimax:MiniMax-M3",
"RETRIEVER": "duckduckgo"
},
"tool_timeout": 300
}
}
}⚠️ Use literals —
INFERENCE_LLM=${INFERENCE_LLM:-default}e similares são template bash-style não-interpolados. v3.0 detecta isso e emite WARN, mas a pipeline quebra silenciosamente se não trocar. Em caso de dúvida, copie valor direto:INFERENCE_LLM=openai:gpt-4o-mini.
Migration from v2.x
- "OPENAI_API_KEY": "...",
- "OPENAI_BASE_URL": "https://api.venice.ai/api/v1",
- "FAST_LLM": "...",
- "SMART_LLM": "...",
- "STRATEGIC_LLM": "...",
- "EMBEDDING_LLM": "...",
- "PERCIVAL_LLM_PROVIDER_ALIASES": "venice:,minimax:,openrouter:",
- "BRAVE_API_KEY": "...",
+ "INFERENCE_API_KEY": "...",
+ "INFERENCE_BASE_URL": "...",
+ "INFERENCE_LLM": "<provider>:<model>",
+ "RETRIEVER": "duckduckgo" // ou "brave" + BRAVE_API_KEY se quiserBreaking changes v2.x → v3.0:
❌
OPENAI_*env vars (still accepted as fallback with deprecation log; will be removed in v4.0).❌
FAST_LLM/SMART_LLM/STRATEGIC_LLM/EMBEDDING_LLMper-slot overrides (still honored when set, butINFERENCE_LLMis canonical).❌ Llm-bridge expansion
venice:,minimax:,openrouter:(now auto-detected fromINFERENCE_BASE_URL).❌
BRAVE_API_KEYis needed only ifRETRIEVER=brave.✅ v3.0 NEW:
research_quick_brief,research_synthesis,research_health_diagnoseprompts.✅ v3.0 NEW: strict validation on
deep_research(include_context)— accepts only realbool.'yes'/'false'/1are rejected at the framework level (Pydantic StrictBool in the type annotation).
⚠️ Known Limitations (v3.0.x)
These are honest design constraints, not bug reports:
Embeddings require an OpenAI-compatible provider. When you set
INFERENCE_LLM=minimax:...(or venice:, openrouter:, etc.) for chat synthesis, the embedding slot is left unset instead of receiving the chat model —gpt-researcher/memory/embeddings.pypreviously received whateverINFERENCE_LLMsaid, which silently produced garbage. See troubleshooting below.The four-slot override is gone if you skip
INFERENCE_LLM. When you provideSTRATEGIC_LLM/FAST_LLM/SMART_LLM/EMBEDDING_LLMbut notINFERENCE_LLM, only the slots you explicitly set are honored. Workaround: setINFERENCE_LLM=to the chat-model you want everywhere.gpt-researcher >= 0.16.0upstream bug. The vendored copy in.venv(afteruv sync) hitsNameError: name 'Any' is not definedat import time. We've applied afrom __future__ import annotationspatch in our local venv (seescripts/patch_gpt_researcher.py). Without it, the server never boots. If you destroy your venv, re-runuv run python scripts/patch_gpt_researcher.pyafteruv sync.DuckDuckGo retriever rate-limits on heavy traffic. DuckDuckGo doesn't publish rate limits but returns
HTTP 429after sustained scraping. Operators chaining large batched research should consider Brave (withBRAVE_API_KEY) or a local SearXNG instance.include_contextschema strictness (v3.0+).Pydantic StrictBoolrejects'yes','false',1,0,dict, etc. at the framework layer before the handler runs. Agents that previously passed'yes'/'false'will see aToolError. Fix: pass realTrue/False.
🛠️ Development & Testing
cd percival.OS_Dev
uv sync
uv run percival-deep-researchTest runs
# Whole suite (353 passed + 3 skipped; no integration deps needed).
uv run pytest -q
# Just the round 4+5 regression tests (placeholder detection, dedup, etc.).
uv run pytest tests/test_audit_round4_nano.py tests/test_audit_round5_placeholder.py -v
# Smoke test (boots, version prints):
INFERENCE_API_KEY=sk-fake INFERENCE_BASE_URL=https://api.minimax.io/v1 \
INFERENCE_LLM=minimax:MiniMax-M3 \
timeout 4 uv run --no-sync percival-deep-research🛟 Troubleshooting (v3.0.x)
Error: Unsupported ${INFERENCE_LLM. (N0)
Cause: Your .env or config.json contains a bash-style placeholder
template (${VAR} or ${VAR:-default}) that the loader could not
interpolate. The literal string then hits gpt_researcher.config.config. parse_llm and produces a cryptic Unsupported ${INFERENCE_LLM..
v3.0 detection: If this happens, you'll also see this WARN at boot:
[S6] INFERENCE_LLM='${INFERENCE_LLM:-openai:gpt-4o-mini}' looks like an
UN-EXPANDED template placeholder. Most likely cause: `.env` or
`config.json` referenced a placeholder that the loader couldn't
interpolate.Fix:
- INFERENCE_LLM=${INFERENCE_LLM:-openai:gpt-4o-mini}
+ INFERENCE_LLM=openai:gpt-4o-miniOr in config.json:
- "INFERENCE_LLM": "${INFERENCE_LLM:-openai:gpt-4o-mini}"
+ "INFERENCE_LLM": "openai:gpt-4o-mini"The same WARN [S6] fires on missing
:in the value (e.g.,INFERENCE_LLM=gpt-4o-mini) and on python-format%(...)sand on f-string{...}templates — all of these failparse_llmthe same way. The WARN points you to the exact file (.envorconfig.json).
"401 Incorrect API key" on custom gateway (B3, e.g. Venice, MiniMax)
Cause: gpt-researcher/memory/embeddings.py (upstream, not editable)
reads os.environ["OPENAI_BASE_URL"] / os.environ["OPENAI_API_KEY"]
directly. Setting only INFERENCE_BASE_URL / INFERENCE_API_KEY is
insufficient — populate_inference_slots() in llm_bridge.py
propagates these env vars to the legacy OPENAI_* namespace. To use on
custom gateway:
INFERENCE_API_KEY=sk-your-gateway-key
INFERENCE_BASE_URL=https://api.venice.ai/api/v1
INFERENCE_LLM=venice:llama-3.3-70bAfter startup, log line should show:
Inference provider: venice (auto-detected from INFERENCE_BASE_URL)If it says openai, your INFERENCE_BASE_URL is wrong (must contain
the gateway host — api.venice.ai, api.minimax.io, openrouter.ai).
pytest -q reports failures on a clean machine (B4)
Integration tests connect to localhost:8000 and fail if no server is
up. v2.2.1+ adds an autouse fixture in tests/conftest.py that
skips integration tests without a server:
uv run pytest -q
# Expected (v2.2.1+): N passed, M skippedIf you need to run them, start a server first:
# In one terminal:
MCP_TRANSPORT=sse uv run --no-sync percival-deep-research
# Then in another:
uv run pytest__version__ reports the wrong number
Re-install the editable package:
uv pip install -e . --force-reinstall
# OR
uv syncThe regression test
tests/test_audit_round3_nano.py::test_version_correto_no_runtime will
fail loudly on any future drift.
research://topic with space fails with invalid domain character
FastMCP 3.4 Pydantic validator rejects non-ASCII in URI domains. v2.2.0+ added percent-decode server-side, so callers can either:
# Option A: percent-encode the topic (recommended)
await client.read_resource("research://S%C3%A3o%20Paulo")
# Option B: encode at the call site
import urllib.parse
uri = "research://" + urllib.parse.quote("São Paulo", safe="")
await client.read_resource(uri)include_context='yes' returns ToolError (N8/N9)
This was v2.x lax-mode accepting string-coerced bool, v3.0+ enforces
strict bool. Pass real True/False:
# Wrong (was accepted in <v3.0):
await client.call_tool("research_deep", {"query": "x", "include_context": "yes"})
# Right:
await client.call_tool("research_deep", {"query": "x", "include_context": True})Affected: 'yes', 'false', 1, 0, {} and similar truthy/falsy
non-bools. The framework (Pydantic StrictBool) now rejects these with
a clear ToolError before our handler runs.
Spurious Future exception was never retrieved in server logs
Fixed in v3.0 (S3 fix): deep_research rate-limit-reject branch now
calls future.exception() to consume the exception cleanly. If you
still see this on a fork, ensure the in-flight dedup path consumes the
exception:
if not future.done():
future.set_exception(RuntimeError("..."))
future.exception() # <- this line cleans the warningComponent already exists: template:research://{topic} at boot
Two triggers known in FastMCP 3.4:
Running
server.pywithpython -i server.py(interactive mode imports modules twice).Subprocess imports the package via
importlib.reload().
The regression test
tests/test_audit_round3_nano.py::test_apenas_um_template_research_topic
catches this.
Boot emits [S6] WARN even though INFERENCE_LLM looks valid
Possible causes (after v3.0 review):
A stray
}character somewhere (e.g.,model-v2}typo). v3.0 removed}as a false-positive signal, so this should not trigger anymore. If still triggered, file a bug.A leftover
gpt-{name}template. v3.0 retains{as a placeholder signal — replace with literal values.
📚 About the Project
This server is an integral module of the percival.OS project. It enables Nanobot to perform complex research tasks that require multiple steps of validation and synthesis.
Main Repository: https://github.com/bill-kopp-ai-dev/percival.OS
License: MIT
📝 Versioning
Version | Status | Notes |
3.0.0 | ✅ current | 4 new prompts; strict-bool on |
2.3.x | 🟠 superseded | last with |
2.2.x | 🟠 superseded | single-endpoint inference introduced |
2.1.x | 🟢 legacy | four-slot |
1.0.x | 🟢 legacy | initial release |
See CHANGELOG.md for the complete history.
Developed with ❤️ by the percival.OS Team
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceAn MCP server that utilizes LangGraph and Google Gemini to conduct comprehensive research through multi-iteration deep searches and quick results. It provides high-quality analysis with automated citations and grounding metadata for thorough investigations.Last updated2MIT
- AlicenseAqualityDmaintenanceA comprehensive MCP server providing 15 web tools including search, scraping, screenshots, SEO audits, and DNS/SSL checks through a single installation. It delivers clean, LLM-optimized outputs so AI agents can focus on reasoning rather than parsing raw HTML.Last updated1525MIT
- Alicense-qualityDmaintenanceAn MCP server that enables AI agents to perform search-augmented queries and deep multi-source research using the Perplexity API.Last updated4023Apache 2.0
- AlicenseAqualityBmaintenanceMCP server for AI-powered research using Gemini. Provides fast grounded web search, deep autonomous research, URL extraction, and session management.Last updated69MIT
Related MCP Connectors
Driflyte MCP server which lets AI assistants query topic-specific knowledge from web and GitHub.
MCP server connecting AI agents to non-custodial staking data across 130+ networks.
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/bill-kopp-ai-dev/percival-deep-research'
If you have feedback or need assistance with the MCP directory API, please join our Discord server