LABSCO SUMMARY
One call that runs for minutes — configure the timeout before you configure anything else.
This is not a search tool that returns in a second; a research pass takes about 2 minutes by the project's own account, and a client with a default timeout will cut it off mid-run. The other thing to settle early is the pairing: a strong thinking model with a high-output task model behaves very differently from using one model for both.
What it is
A self-hosted deep-research application that also serves an MCP endpoint. It splits the work between a thinking model and a task model, pairs them with a web search provider, and produces a research report; because you deploy it, the data and the model choice stay yours.
What you get
- A research endpoint any MCP client can call, over Streamable HTTP at
/api/mcpor SSE at/api/mcp/sse - A wide choice of models: Gemini, OpenAI, Anthropic, Deepseek, Grok, Mistral, Azure OpenAI, OpenRouter, Ollama and any OpenAI-compatible endpoint, selected with
MCP_AI_PROVIDER - Web search through Searxng, Tavily, Firecrawl, Exa, Bocha or Brave, selected with
MCP_SEARCH_PROVIDER, so models without built-in search can still work over the live web - Separate thinking and task models, set with
MCP_THINKING_MODELandMCP_TASK_MODEL, to balance depth against speed and output length - Optional protection: set
ACCESS_PASSWORDand the MCP endpoint requires a Bearer token - The same deployment's web app for the interactive side: local knowledge base uploads, editable reports, knowledge graphs and research history
Requirements
Your own deployment — one-click to Vercel or Cloudflare Pages, or the Docker image — plus keys for the model provider and search engine you pick. The four MCP variables above are global environment variables and the service will not run without them. Set a long client timeout: the README uses 600, because a research run takes minutes. Version 0.11.1, MIT licensed.
Setup effort
Follow the published steps — docker pull xiangfa/deep-research:latest
USE CASES
01
Getting a researched brief instead of a search summary
Ask once and let the deployment plan, search the live web and write the report — minutes of work returned as one result.
02
Adding web search to a model that has none
Point MCP_SEARCH_PROVIDER at Tavily, Searxng or another supported engine so the research runs over current pages regardless of the model you chose.
03
Keeping research on infrastructure you control
Deploy it yourself to Vercel, Cloudflare or Docker with your own provider keys, and set ACCESS_PASSWORD so the endpoint needs a Bearer token.
04
Continuing the work after the report lands
Open the same deployment's web app to edit the report, add your own documents as a local knowledge base, or generate a knowledge graph from it.
BEFORE YOU INSTALL
What to know first
Requires
GOOGLE_GENERATIVE_AI_API_KEY in your environment
Where it runs
Both documented setups run the server on your machine.
INSTALLATION
Connect your client
Server setup
TERMINAL
docker pull xiangfa/deep-research:latest
docker run -d --name deep-research -p 3333:3000 -e ACCESS_PASSWORD=<YOUR_ACCESS_PASSWORD> -e GOOGLE_GENERATIVE_AI_API_KEY=AIzaSy... xiangfa/deep-researchSet the MCP globals MCP_AI_PROVIDER, MCP_SEARCH_PROVIDER, MCP_THINKING_MODEL and MCP_TASK_MODEL, plus the matching model/search-engine variables from env.tpl
Add the mcpServers block pointing at /api/mcp (add the Authorization header if ACCESS_PASSWORD is set)
MCP Clients
Any MCP client
ANY MCP CLIENT · JSON
{
"mcpServers": {
"deep-research": {
"url": "http://127.0.0.1:3333/api/mcp",
"transportType": "streamable-http",
"timeout": 600
}
}
}The Docker command above publishes the app on host port 3333 (-p 3333:3000), so this URL uses 3333. If you run the local dev server instead, it listens on 3000.
Any MCP client — password
ANY MCP CLIENT — PASSWORD · JSON
{
"mcpServers": {
"deep-research": {
"url": "http://127.0.0.1:3333/api/mcp",
"transportType": "streamable-http",
"timeout": 600,
"headers": {
"Authorization": "Bearer <YOUR_ACCESS_PASSWORD>"
}
}
}
}The Docker command above publishes the app on host port 3333 (-p 3333:3000), so this URL uses 3333. If you run the local dev server instead, it listens on 3000.