deep-research Documentation

Use any LLMs (Large Language Models) for Deep Research. Support SSE API and MCP server.

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy deep-research on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name deep-research -p 3333:3333 --restart always deep-research
Configured Services & Ports
โš™๏ธ deep-research
image: deep-research
๐Ÿ”Œ Ports: 3333:3000
docker-compose.yml
yaml (docker-compose.yml)
version: "3.9"
services:
  deep-research:
    build:
      context: .
      dockerfile: Dockerfile
    image: deep-research
    container_name: deep-research
    env_file:
      - .env
    ports:
      - "3333:3000"

File: README.md

Lightning-Fast Deep Research Report

Deep Research uses a variety of powerful AI models to generate in-depth research reports in just a few minutes. It leverages advanced "Thinking" and "Task" models, combined with an internet connection, to provide fast and insightful analysis on a variety of topics. Your privacy is paramount - all data is processed and stored locally.

โœจ Features

  • Rapid Deep Research: Generates comprehensive research reports in about 2 minutes, significantly accelerating your research process.
  • Multi-platform Support: Supports rapid deployment to Vercel, Cloudflare and other platforms.
  • Powered by AI: Utilizes the advanced AI models for accurate and insightful analysis.
  • Privacy-Focused: Your data remains private and secure, as all data is stored locally on your browser.
  • Support for Multi-LLM: Supports a variety of mainstream large language models, including Gemini, OpenAI, Anthropic, Deepseek, Atlas Cloud, Grok, Mistral, Azure OpenAI, any OpenAI Compatible LLMs, OpenRouter, Ollama, etc.
  • Support Web Search: Supports search engines such as Searxng, Tavily, Firecrawl, fastCRW, Exa, Bocha, Brave, etc., allowing LLMs that do not support search to use the web search function more conveniently.
  • Thinking & Task Models: Employs sophisticated "Thinking" and "Task" models to balance depth and speed, ensuring high-quality results quickly. Support switching research models.
  • Support Further Research: You can refine or adjust the research content at any stage of the project and support re-research from that stage.
  • Local Knowledge Base: Supports uploading and processing text, Office, PDF and other resource files to generate local knowledge base.
  • Artifact: Supports editing of research content, with two editing modes: WYSIWYM and Markdown. It is possible to adjust the reading level, article length and full text translation.
  • Knowledge Graph: It supports one-click generation of knowledge graph, allowing you to have a systematic understanding of the report content.
  • Research History: Support preservation of research history, you can review previous research results at any time and conduct in-depth research again.
  • Local & Server API Support: Offers flexibility with both local and server-side API calling options to suit your needs.
  • Support for SaaS and MCP: You can use this project as a deep research service (SaaS) through the SSE API, or use it in other AI services through MCP service.
  • Support PWA: With Progressive Web App (PWA) technology, you can use the project like a software.
  • Support Multi-Key payload: Support Multi-Key payload to improve API response efficiency.
  • Multi-language Support: English, ็ฎ€ไฝ“ไธญๆ–‡, Espaรฑol.
  • Built with Modern Technologies: Developed using Next.js 15 and Shadcn UI, ensuring a modern, performant, and visually appealing user experience.
  • MIT Licensed: Open-source and freely available for personal and commercial use under the MIT License.

๐ŸŽฏ Roadmap

  • Support preservation of research history
  • Support editing final report and search results
  • Support for other LLM models
  • Support file upload and local knowledge base
  • Support SSE API and MCP server

๐Ÿš€ Getting Started

Use Free Gemini (recommend)

  1. Get Gemini API Key

  2. One-click deployment of the project, you can choose to deploy to Vercel or Cloudflare

    Currently the project supports deployment to Cloudflare, but you need to follow How to deploy to Cloudflare Pages to do it.

  3. Start using

Use Other LLM

  1. Deploy the project to Vercel or Cloudflare
  2. Set the LLM API key
  3. Set the LLM API base URL (optional)
  4. Start using

โŒจ๏ธ Development

Follow these steps to get Deep Research up and running on your local browser.

Prerequisites

Installation

  1. Clone the repository:

    bash
    git clone https://github.com/u14app/deep-research.git
    cd deep-research
  2. Install dependencies:

    bash
    pnpm install  # or npm install or yarn install
  3. Set up Environment Variables:

    You need to modify the file env.tpl to .env, or create a .env file and write the variables to this file.

    bash
    # For Development
    cp env.tpl .env.local
    # For Production
    cp env.tpl .env
  4. Run the development server:

    bash
    pnpm dev  # or npm run dev or yarn dev

    Open your browser and visit http://localhost:3000 to access Deep Research.

Custom Model List

The project allow custom model list, but only works in proxy mode. Please add an environment variable named NEXT_PUBLIC_MODEL_LIST in the .env file or environment variables page.

Custom model lists use , to separate multiple models. If you want to disable a model, use the - symbol followed by the model name, i.e. -existing-model-name. To only allow the specified model to be available, use -all,+new-model-name.

๐Ÿšข Deployment

Vercel

Cloudflare

Currently the project supports deployment to Cloudflare, but you need to follow How to deploy to Cloudflare Pages to do it.

Docker

The Docker version needs to be 20 or above, otherwise it will prompt that the image cannot be found.

โš ๏ธ Note: Most of the time, the docker version will lag behind the latest version by 1 to 2 days, so the "update exists" prompt will continue to appear after deployment, which is normal.

bash
docker pull xiangfa/deep-research:latest
docker run -d --name deep-research -p 3333:3000 xiangfa/deep-research

You can also specify additional environment variables:

bash
docker run -d --name deep-research \
   -p 3333:3000 \
   -e ACCESS_PASSWORD=your-password \
   -e GOOGLE_GENERATIVE_AI_API_KEY=AIzaSy... \
   xiangfa/deep-research

or build your own docker image:

bash
docker build -t deep-research .
docker run -d --name deep-research -p 3333:3000 deep-research

If you need to specify other environment variables, please add -e key=value to the above command to specify it.

Deploy using docker-compose.yml:

bash
version: '3.9'
services:
   deep-research:
      image: xiangfa/deep-research
      container_name: deep-research
      environment:
         - ACCESS_PASSWORD=your-password
         - GOOGLE_GENERATIVE_AI_API_KEY=AIzaSy...
      ports:
         - 3333:3000

or build your own docker compose:

bash
docker compose -f docker-compose.yml build

Static Deployment

You can also build a static page version directly, and then upload all files in the out directory to any website service that supports static pages, such as Github Page, Cloudflare, Vercel, etc..

bash
pnpm build:export

โš™๏ธ Configuration

As mentioned in the "Getting Started" section, Deep Research utilizes the following environment variables for server-side API configurations:

Please refer to the file env.tpl for all available environment variables.

Important Notes on Environment Variables:

  • Privacy Reminder: These environment variables are primarily used for server-side API calls. When using the local API mode, no API keys or server-side configurations are needed, further enhancing your privacy.

  • Multi-key Support: Supports multiple keys, each key is separated by ,, i.e. key1,key2,key3.

  • Security Setting: By setting ACCESS_PASSWORD, you can better protect the security of the server API.

  • Make variables effective: After adding or modifying this environment variable, please redeploy the project for the changes to take effect.

๐Ÿ“„ API documentation

Currently the project supports two forms of API: Server-Sent Events (SSE) and Model Context Protocol (MCP).

Server-Sent Events API

The Deep Research API provides a real-time interface for initiating and monitoring complex research tasks.

Recommended to use the API via @microsoft/fetch-event-source, to get the final report, you need to listen to the message event, the data will be returned in the form of a text stream.

POST method

Endpoint: /api/sse

Method: POST

Body:

typescript
interface SSEConfig {
  // Research topic
  query: string;
  // AI provider, Possible values โ€‹โ€‹include: google, openai, anthropic, deepseek, atlascloud, xai, mistral, azure, openrouter, openaicompatible, pollinations, ollama
  provider: string;
  // Thinking model id
  thinkingModel: string;
  // Task model id
  taskModel: string;
  // Search provider, Possible values โ€‹โ€‹include: model, tavily, firecrawl, crw, exa, bocha, searxng
  searchProvider: string;
  // Response Language, also affects the search language. (optional)
  language?: string;
  // Maximum number of search results. Default, `5` (optional)
  maxResult?: number;
  // Whether to include content-related images in the final report. Default, `true`. (optional)
  enableCitationImage?: boolean;
  // Whether to include citation links in search results and final reports. Default, `true`. (optional)
  enableReferences?: boolean;
}

Headers:

typescript
interface Headers {
  "Content-Type": "application/json";
  // If you set an access password
  // Authorization: "Bearer YOUR_ACCESS_PASSWORD";
}

See the detailed API documentation.

GET method

This is an interesting implementation. You can watch the whole process of deep research directly through the URL just like watching a video.

You can access the deep research report via the following link:

text
http://localhost:3000/api/sse/live?query=AI+trends+for+this+year&provider=pollinations&thinkingModel=openai&taskModel=openai-fast&searchProvider=searxng

Query Params:

typescript
// The parameters are the same as POST parameters
interface QueryParams extends SSEConfig {
  // If you set the `ACCESS_PASSWORD` environment variable, this parameter is required
  password?: string;
}

Model Context Protocol (MCP) Server

Currently supports StreamableHTTP and SSE Server Transport.

StreamableHTTP server endpoint: /api/mcp, transport type: streamable-http

SSE server endpoint: /api/mcp/sse, transport type: sse

json
{
  "mcpServers": {
    "deep-research": {
      "url": "http://127.0.0.1:3000/api/mcp",
      "transportType": "streamable-http",
      "timeout": 600
    }
  }
}

Note: Since deep research take a long time to execute, you need to set a longer timeout to avoid interrupting the study.

If your server sets ACCESS_PASSWORD, the MCP service will be protected and you need to add additional headers parameters:

json
{
  "mcpServers": {
    "deep-research": {
      "url": "http://127.0.0.1:3000/api/mcp",
      "transportType": "streamable-http",
      "timeout": 600,
      "headers": {
        "Authorization": "Bearer YOUR_ACCESS_PASSWORD"
      }
    }
  }
}

Enabling MCP service requires setting global environment variables:

bash
# MCP Server AI provider
# Possible values โ€‹โ€‹include: google, openai, anthropic, deepseek, atlascloud, xai, mistral, azure, openrouter, openaicompatible, pollinations, ollama
MCP_AI_PROVIDER=google
# MCP Server search provider. Default, `model`
# Possible values โ€‹โ€‹include: model, tavily, firecrawl, crw, exa, bocha, searxng
MCP_SEARCH_PROVIDER=tavily
# MCP Server thinking model id, the core model used in deep research.
MCP_THINKING_MODEL=gemini-2.0-flash-thinking-exp
# MCP Server task model id, used for secondary tasks, high output models are recommended.
MCP_TASK_MODEL=gemini-2.0-flash-exp

Note: To ensure that the MCP service can be used normally, you need to set the environment variables of the corresponding model and search engine. For specific environment variable parameters, please refer to env.tpl.

๐Ÿช„ How it works

  1. Research topic

    • Input research topic
    • Use local research resources (optional)
    • Start thinking (or rethinking)
  2. Propose your ideas

    • The system asks questions
      • Answer system questions (optional)
      • Write a research plan (or rewrite the research plan)
    • The system outputs the research plan
      • Start in-depth research (or re-research)
      • The system generates SERP queries
  3. Information collection

    • Initial research
      • Retrieve local research resources based on SERP queries
      • Collect information from the Internet based on SERP queries
    • In-depth research (this process can be repeated)
      • Propose research suggestions (optional)
      • Start a new round of information collection (the process is the same as the initial research)
  4. Generate Final Report

    • Make a writing request (optional)
    • Summarize all research materials into a comprehensive Markdown report
    • Regenerate research report (optional)
mermaid
flowchart TB
    A[Research Topic]:::start

    subgraph Propose[Propose your ideas]
        B1[System asks questions]:::process
        B2[System outputs the research plan]:::process
        B3[System generates SERP queries]:::process
        B1 --> B2
        B2 --> B3
    end

    subgraph Collect[Information collection]
        C1[Initial research]:::collection
        C1a[Retrieve local research resources based on SERP queries]:::collection
        C1b[Collect information from the Internet based on SERP queries]:::collection
        C2[In-depth research]:::recursive
        Refine{More in-depth research needed?}:::decision

        C1 --> C1a
        C1 --> C1b
        C1a --> C2
        C1b --> C2
        C2 --> Refine
        Refine -->|Yes| C2
    end

    Report[Generate Final Report]:::output

    A --> Propose
    B3 --> C1

    %% Connect the exit from the loop/subgraph to the final report
    Refine -->|No| Report

    %% Styling
    classDef start fill:#7bed9f,stroke:#2ed573,color:black
    classDef process fill:#70a1ff,stroke:#1e90ff,color:black
    classDef recursive fill:#ffa502,stroke:#ff7f50,color:black
    classDef output fill:#ff4757,stroke:#ff6b81,color:black
    classDef collection fill:#a8e6cf,stroke:#3b7a57,color:black
    classDef decision fill:#c8d6e5,stroke:#8395a7,color:black

    class A start
    class B1,B2,B3 process
    class C1,C1a,C1b collection
    class C2 recursive
    class Refine decision
    class Report output

๐Ÿ™‹ FAQs

Why does my Ollama or SearXNG not work properly and displays the error TypeError: Failed to fetch?

If your request generates CORS due to browser security restrictions, you need to configure parameters for Ollama or SearXNG to allow cross-domain requests. You can also consider using the server proxy mode, which is a backend server that makes requests, which can effectively avoid cross-domain issues.

๐Ÿ›ก๏ธ Privacy

Deep Research is designed with your privacy in mind. All research data and generated reports are stored locally on your machine. We do not collect or transmit any of your research data to external servers (unless you are explicitly using server-side API calls, in which case data is sent to API through your configured proxy if any). Your privacy is our priority.

๐Ÿ™ Acknowledgements

  • Next.js - The React framework for building performant web applications.
  • Shadcn UI - Beautifully designed components that helped streamline the UI development.
  • AI SDKs - Powering the intelligent research capabilities of Deep Research.
  • Deep Research - Thanks to the project dzhng/deep-research for inspiration.

๐Ÿค Contributing

We welcome contributions to Deep Research! If you have ideas for improvements, bug fixes, or new features, please feel free to:

  1. Fork the repository.
  2. Create a new branch for your feature or bug fix.
  3. Make your changes and commit them.
  4. Submit a pull request.

For major changes, please open an issue first to discuss your proposed changes.

โœ‰๏ธ Contact

If you have any questions, suggestions, or feedback, please create a new issue.

๐Ÿ“ License

Deep Research is released under the MIT License. This license allows for free use, modification, and distribution for both commercial and non-commercial purposes.


File: docs/deep-research-api-doc.md

Deep Research API Documentation

Overview

The Deep Research API provides a real-time interface for initiating and monitoring complex research tasks. Leveraging Server-Sent Events (SSE), it delivers updates, information, message, progress, and errors as they occur, allowing clients to receive continuous streams of data without polling.

Protocol

This API uses Server-Sent Events (SSE) over HTTP. Clients should establish an HTTP connection and keep it open to receive a stream of events from the server.

Data Format

All data sent via SSE adheres to the following structure:

text
event: EventName
data: JSON_String
  • event: Specifies the type of event being sent (e.g., infor, message, reasoning, progress, error).
  • data: A string containing a JSON object relevant to the event type.
  • A double newline (\n\n) signifies the end of an event block.

API config

Recommended to use the API via @microsoft/fetch-event-source.

Endpoint: /api/sse

Method: POST

Body:

typescript
interface Config {
  // Research topic
  query: string;
  // AI provider, Possible values โ€‹โ€‹include: google, openai, anthropic, deepseek, xai, mistral, azure, openrouter, openaicompatible, pollinations, ollama
  provider: string;
  // Thinking model id
  thinkingModel: string;
  // Task model id
  taskModel: string;
  // Search provider, Possible values โ€‹โ€‹include: model, tavily, firecrawl, crw, exa, bocha, searxng
  searchProvider: string;
  // Response Language, also affects the search language. (optional)
  language?: string;
  // Maximum number of search results. Default, `5` (optional)
  maxResult?: number;
  // Whether to include content-related images in the final report. Default, `true`. (optional)
  enableCitationImage?: boolean;
  // Whether to include citation links in search results and final reports. Default, `true`. (optional)
  enableReferences?: boolean;
  // Override built-in prompt templates. You can provide one or more prompt keys as needed. (optional)
  promptOverrides?: Partial<{
    systemInstruction: string;
    outputGuidelinesPrompt: string;
    systemQuestionPrompt: string;
    reportPlanPrompt: string;
    serpQueriesPrompt: string;
    queryResultPrompt: string;
    citationRulesPrompt: string;
    searchResultPrompt: string;
    searchKnowledgeResultPrompt: string;
    reviewPrompt: string;
    finalReportCitationImagePrompt: string;
    finalReportReferencesPrompt: string;
    finalReportPrompt: string;
  }>;
}

Headers:

typescript
interface Headers {
  "Content-Type": "application/json";
  // If you set an access password
  // Authorization: "Bearer YOUR_ACCESS_PASSWORD";
}

For specific usage parameter forms, see the example code.

Response Events

The API streams data as a series of events. Each event has a type (event) and associated data (data).

General Structure

text
event: [event_type]
data: [JSON_payload]

Event Types

The following event types are supported:

  • infor
  • message
  • reasoning
  • progress
  • error

`infor` Event

Sent at the beginning of the stream (or upon specific requests) to provide initial information about the API instance or the research session.

Description: Provides basic information about the running API instance.

Data Structure (data field): A JSON string representing the following structure:

Parameter Type Description
name string Project name
version string Current API version
typescript
interface InforEvent {
  // Project name
  name: string;
  // Current API version
  version: string;
}

Example:

text
event: infor
data: {"name":"deep-research","version":"0.1.0"}

`message` Event

Used to send text content of deep research to the client.

Description: Delivers textual messages during the research process.

Data Structure (data field): A JSON string representing the following structure:

Parameter Type Description Notes
type string Type of the message content Currently only "text" is supported.
text string The message content (Markdown format). Optional for future types, but required for "text".
typescript
interface MessageEvent {
  // Message type, currently only "text" is supported
  type: "text";
  // Textual data
  text?: string;
}

Example:

text
event: message
data: {"type":"text","text":"This is a **markdown** string."}

`reasoning` Event

Used to send thinking content of deep research to the client. Some thinking models support output thinking process.

Description: Delivers textual messages during the research process.

Data Structure (data field): A JSON string representing the following structure:

Parameter Type Description Notes
type string Type of the reasoning content Currently only "text" is supported.
text string The reasoning content (Markdown format). Required for "text".
typescript
interface ReasoningEvent {
  // Reasoning type, currently only "text" is supported
  type: "text";
  // Textual data
  text: string;
}

Example:

text
event: message
data: {"type":"text","text":"Output thinking process"}

`progress` Event

Communicates the current step and status of the research task execution. This is crucial for providing real-time feedback on the process flow.

Description: Indicates the progress of the research task, including the current step and its status (start or end).

Data Structure (data field): A JSON string representing the following structure:

Parameter Type Description Notes
step "report-plan" | "serp-query" | "task-list" | "search-task" | "final-report" The identifier of the current step in the research process. See "Possible step Values" below.
status "start" | "end" The status of the current step. Indicates if the step is starting or ending. See "Possible status Values" below.
name string A descriptive name for the specific instance of the step (e.g., for a specific search task). Included only when step is "search-task".
data any Optional data relevant to the step's outcome or details. May be included when status is "end". The content varies by step.
typescript
interface ProgressEvent {
  // Current step
  step:
    | "report-plan"
    | "serp-query"
    | "task-list"
    | "search-task"
    | "final-report";
  // Status of the step
  status: "start" | "end";
  // Name of the specific task (e.g., search query)
  name?: string;
  // Data related to the step's outcome or details
  data?: any;
}

Possible step Values:

  • report-plan: The system is generating or processing the overall report plan.
  • serp-query: The system is performing a Search Engine Results Page (SERP) query.
  • task-list: The system is generating or processing a list of specific research tasks.
  • search-task: The system is executing a specific search task. This step includes the name parameter.
  • final-report: The system is compiling or finalizing the comprehensive research report.

Possible status Values:

  • start: Indicates that the specified step has just begun.
  • end: Indicates that the specified step has just finished.

Example:

text
event: progress
data: {"step":"search-task","status":"start","name":"AI trends for this year"}

event: progress
data: {"step":"search-task","status":"end","name":"AI trends for this year","data":{"results_count": 15}}

`error` Event

Sent when an error occurs during the research process that prevents the task from completing successfully or requires user attention.

Description: Signals that an error has occurred.

Data Structure (data field): A JSON string typically containing information about the error. A common structure is:

Parameter Type Description Notes
message string A human-readable description of the error.
typescript
interface ErrorEvent {
  // A human-readable description of the error.
  message: string;
}

Example:

text
event: error
data: {"message":"Invalid query parameters."}

Error Handling

Clients should always listen for the error event. Upon receiving an error event, the client should typically display the error message to the user and may consider the current research task terminated unless otherwise specified by the API's behavior.

Client Code Example

This example demonstrates how to connect to the SSE endpoint using EventSource API and listen for the defined event types, specifically focusing on displaying message events.

typescript
import { fetchEventSource } from "@microsoft/fetch-event-source";

const ctrl = new AbortController();

let report = "";
fetchEventSource("/api/sse", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    // If you set an access password
    // Authorization: "Bearer YOUR_ACCESS_PASSWORD",
  },
  body: JSON.stringify({
    query: "AI trends for this year",
    provider: "google",
    thinkingModel: "gemini-2.0-flash-thinking-exp",
    taskModel: "gemini-2.0-flash-exp",
    searchProvider: "model",
    language: "en-US",
    maxResult: 5,
    enableCitationImage: true,
    enableReferences: true,
    promptOverrides: {
      systemInstruction:
        "You are an expert researcher. Keep answers concise and evidence-driven.",
    },
  }),
  signal: ctrl.signal,
  onmessage(msg) {
    const msgData = JSON.parse(msg.data);
    if (msg.event === "message") {
      if (msgData.type === "text") {
        report += msgData.text;
      }
    } else if (msg.event === "progress") {
      console.log(
        `[${data.step}]: ${msgData.name ? `${msgData.name} ` : ""}${
          msgData.status
        }`
      );
      if (msgData.data) console.log(msgData.data);
    } else if (msg.event === "error") {
      throw new Error(msgData.message);
    }
  },
  onclose() {
    console.log(report);
  },
});

File: docs/How-to-deploy-to-Cloudflare-Pages.md

How to deploy your project to Cloudflare Pages

  1. Log in to the Cloudflare dashboard and select your account.
  2. Select Compute(Workers) > Create > Pages.
  3. Click Connect to Git > deep-research > Begin Setup
  4. Framework preset > Next.js > Set Environment Variables (optional) > Save and Deploy
  5. Deploy > Redeploy

Set a custom domain name (optional)

Since the pages.dev domain name cannot be accessed normally in some countries, you can solve this problem by setting a custom domain name.

  1. Select Compute(Workers) > Your project.
  2. Select Custom Domains > Set up a custom domain.