# MCP Server Guide

LDR provides an MCP (Model Context Protocol) server that exposes its research capabilities to AI assistants like Claude Desktop, Claude Code, and OpenClaw. MCP is an open protocol by Anthropic that lets AI applications call external tools over a standardized interface.

The MCP server exposes 8 research tools — 5 research tools and 3 discovery tools — over **STDIO transport only** (local use, no network exposure). MCP support is an optional dependency that must be installed separately.

## Quick Start

### Installation

```bash
pip install "local-deep-research[mcp]"
```

### Claude Desktop Configuration

Add the following to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "local-deep-research": {
      "command": "ldr-mcp",
      "env": {
        "LDR_LLM_PROVIDER": "openai",
        "LDR_LLM_OPENAI_API_KEY": "sk-..."
      }
    }
  }
}
```

### Claude Code Configuration

Add to your `.mcp.json` (project-level) or `~/.claude/mcp.json` (global):

```json
{
  "mcpServers": {
    "local-deep-research": {
      "command": "ldr-mcp",
      "env": {
        "LDR_LLM_PROVIDER": "ollama",
        "LDR_LLM_OLLAMA_URL": "http://localhost:11434"
      }
    }
  }
}
```

### OpenClaw Configuration

Add LDR as a skill in your `openclaw.json`:

```json
{
  "mcpServers": {
    "local-deep-research": {
      "command": "ldr-mcp",
      "env": {
        "LDR_LLM_PROVIDER": "openai",
        "LDR_LLM_OPENAI_API_KEY": "sk-..."
      }
    }
  }
}
```

The configuration format is the same as Claude Desktop. See the [OpenClaw MCP documentation](https://docs.openclaw.com/skills/mcp) for details on skill registration.

### Verify Installation

Run `ldr-mcp` in a terminal. It should start and wait for STDIO input (no output means it's working). Press `Ctrl+C` to stop.

### First Research

Open Claude Desktop and try:

```
Use quick_research to find information about quantum computing applications
```

## Configuration

The MCP server uses the same settings system as the main LDR application. There are no dedicated MCP-specific environment variables. All configuration is done through standard `LDR_*` environment variables, set in the Claude Desktop config's `env` block.

### Environment Variables

**LLM Settings:**

| Variable | Description | Example |
|----------|-------------|---------|
| `LDR_LLM_PROVIDER` | LLM provider | `openai`, `ollama`, `anthropic` |
| `LDR_LLM_MODEL` | Model name | `gpt-4`, `llama3:8b`, `claude-sonnet-4-20250514` |
| `LDR_LLM_OPENAI_API_KEY` | OpenAI API key | `sk-...` |
| `LDR_LLM_TEMPERATURE` | Generation temperature | `0.7` |

**Search Settings:**

| Variable | Description | Example |
|----------|-------------|---------|
| `LDR_SEARCH_TOOL` | Default search engine | `searxng`, `arxiv`, `wikipedia` |
| `LDR_SEARCH_SEARCH_STRATEGY` | Default strategy | `source-based`, `focused-iteration` |
| `LDR_SEARCH_ITERATIONS` | Default iteration count | `2` |
| `LDR_SEARCH_QUESTIONS_PER_ITERATION` | Questions per iteration | `3` |

> **Note:** The strategy variable uses a double underscore (`SEARCH_SEARCH_STRATEGY`) because the settings key is `search.search_strategy`.

**Optional Search API Keys:**

| Variable | Description |
|----------|-------------|
| `LDR_TAVILY_API_KEY` | Tavily search API key |
| `LDR_BRAVE_SEARCH_API_KEY` | Brave Search API key |
| `LDR_SERPAPI_API_KEY` | SerpAPI key |

### Example Configurations

**OpenAI (default):**

```json
{
  "mcpServers": {
    "local-deep-research": {
      "command": "ldr-mcp",
      "env": {
        "LDR_LLM_PROVIDER": "openai",
        "LDR_LLM_MODEL": "gpt-4",
        "LDR_LLM_OPENAI_API_KEY": "sk-..."
      }
    }
  }
}
```

**Ollama (fully local, no API key needed):**

```json
{
  "mcpServers": {
    "local-deep-research": {
      "command": "ldr-mcp",
      "env": {
        "LDR_LLM_PROVIDER": "ollama",
        "LDR_LLM_MODEL": "llama3:8b"
      }
    }
  }
}
```

**Anthropic:**

```json
{
  "mcpServers": {
    "local-deep-research": {
      "command": "ldr-mcp",
      "env": {
        "LDR_LLM_PROVIDER": "anthropic",
        "LDR_LLM_MODEL": "claude-sonnet-4-20250514",
        "LDR_LLM_ANTHROPIC_API_KEY": "sk-ant-..."
      }
    }
  }
}
```

### Logging

All log output goes to **stderr** (stdout is reserved for the JSON-RPC protocol). The log level is hardcoded to `INFO` — there is no environment variable to change it.

## Available Tools

### Research Tools

#### `quick_research`

Fast research summary. Typically takes **1-5 minutes**.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `query` | string | Yes | Research question (max 10,000 chars) |
| `search_engine` | string | No | Search engine to use (e.g., `"searxng"`, `"arxiv"`, `"wikipedia"`) |
| `strategy` | string | No | Research strategy (e.g., `"source-based"`, `"focused-iteration"`) |
| `iterations` | integer | No | Number of search iterations (1-10) |
| `questions_per_iteration` | integer | No | Questions per iteration (1-10) |

**Returns:**

```json
{
  "status": "success",
  "summary": "Research summary text...",
  "findings": ["finding1", "finding2"],
  "sources": ["https://example.com/source1"],
  "iterations": 3,
  "formatted_findings": "Formatted markdown findings..."
}
```

Best for: fast fact-checking, simple queries, getting a quick overview.

---

#### `detailed_research`

Comprehensive research analysis. Typically takes **5-15 minutes**.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `query` | string | Yes | Research question (max 10,000 chars) |
| `search_engine` | string | No | Search engine to use |
| `strategy` | string | No | Research strategy |
| `iterations` | integer | No | Number of search iterations (1-20) |
| `questions_per_iteration` | integer | No | Questions per iteration (1-10) |

**Returns:**

```json
{
  "status": "success",
  "query": "original query",
  "research_id": "unique-id",
  "summary": "Detailed summary...",
  "findings": ["finding1", "finding2"],
  "sources": ["https://example.com/source1"],
  "iterations": 5,
  "formatted_findings": "Formatted markdown findings...",
  "metadata": {"timestamp": "...", "search_tool": "...", "strategy": "..."}
}
```

Best for: in-depth analysis, nuanced topics, comprehensive coverage.

---

#### `generate_report`

Full structured markdown report with sections, citations, and bibliography. Typically takes **10-30 minutes**.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `query` | string | Yes | Research topic (max 10,000 chars) |
| `search_engine` | string | No | Search engine to use |
| `searches_per_section` | integer | No | Searches per report section (1-10, default 2) |

**Returns:**

```json
{
  "status": "success",
  "content": "# Report Title\n\n## Section 1\n...",
  "metadata": {"timestamp": "...", "query": "..."}
}
```

Best for: publication-quality structured reports with proper citations.

---

#### `analyze_documents`

Search and analyze documents in a local collection using RAG. Typically takes **30 seconds - 2 minutes**.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `query` | string | Yes | Search query (max 10,000 chars) |
| `collection_name` | string | Yes | Engine ID of the collection (e.g., `"collection_3"`). Use `list_search_engines()` to find available collections. |
| `max_results` | integer | No | Maximum documents to retrieve (1-100, default 10) |

**Returns:**

```json
{
  "status": "success",
  "summary": "Summary of findings from documents...",
  "documents": [{"content": "...", "metadata": {"source": "file.pdf", "page": 1}}],
  "collection": "my-papers",
  "document_count": 5
}
```

The data flow is: `collection_name` → FAISS index lookup → semantic similarity search → LLM summarization.

Best for: searching uploaded PDFs and documents in local collections. Use `list_search_engines()` to discover available collection IDs.

---

#### `search`

Raw search results without LLM processing. Typically takes **5-30 seconds**. No LLM cost.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `query` | string | Yes | Search query (max 10,000 chars) |
| `engine` | string | Yes | Search engine to use (e.g., `"arxiv"`, `"wikipedia"`, `"searxng"`). Use `list_search_engines()` to see options. |
| `max_results` | integer | No | Maximum results to return (1-100, default 10) |

**Returns:**

```json
{
  "status": "success",
  "query": "quantum computing",
  "engine": "arxiv",
  "result_count": 10,
  "results": [
    {
      "title": "Quantum Computing: An Overview",
      "link": "https://arxiv.org/abs/2301.12345",
      "snippet": "We present a comprehensive overview..."
    }
  ]
}
```

Common engines: `arxiv` (academic papers), `pubmed` (medical literature), `wikipedia` (encyclopedic), `searxng` (meta-search), `openclaw` (legal case law), `github` (code/repos), `semantic_scholar` (citations). Use `list_search_engines()` for the full list.

Best for: raw search results for your own analysis, quick lookups, checking what sources are available before running full research. Especially useful for **monitoring and subscriptions** — check for new content regularly without LLM cost.

### Discovery Tools

These tools return instantly and are useful for exploring available options.

#### `list_search_engines`

Returns available search engines with their descriptions, strengths, weaknesses, and whether they require an API key or run locally.

#### `list_strategies`

Returns available research strategies with their names and descriptions.

#### `get_configuration`

Returns the current server configuration including LLM provider, model, temperature, and search defaults. **API keys are intentionally excluded** from the response.

## Research Strategies Guide

LDR supports the following research strategies via MCP:

| Strategy | Speed | Accuracy | Best For |
|----------|-------|----------|----------|
| `source-based` | Medium | High | Topics needing authoritative citations |
| `focused-iteration` | Medium | Highest (~95%) | Complex factual / technical topics |
| `focused-iteration-standard` | Medium | High | Comprehensive long-form answers with citations |
| `topic-organization` | Medium | High | Structured output clustered by theme |
| `langgraph-agent` | Varies | High | Autonomous agentic research across engines |

Use `list_strategies()` to see all available strategies and their descriptions.

## Error Handling

All tool calls return structured error responses when something goes wrong. Errors are classified into these categories:

| Error Type | Cause | User-Facing Message |
|------------|-------|---------------------|
| `validation_error` | Bad parameters (empty query, out-of-range values) | Specific message (e.g., "Query cannot be empty") |
| `auth_error` | Invalid or missing API key (401) | "...failed (auth_error). Check server logs." |
| `service_unavailable` | Provider or search engine down (503) | "...failed (service_unavailable). Check server logs." |
| `timeout` | Operation took too long | "...failed (timeout). Check server logs." |
| `rate_limit` | API quota exceeded (429) | "...failed (rate_limit). Check server logs." |
| `connection_error` | Network connectivity issue | "...failed (connection_error). Check server logs." |
| `model_not_found` | Model doesn't exist (404) | "...failed (model_not_found). Check server logs." |
| `unknown` | Unclassified error | "...failed (unknown). Check server logs." |

All errors are logged to stderr with full detail. User-facing messages are sanitized — no stack traces or API keys are exposed.

## Security Model

- **STDIO-only transport** — The server runs `mcp.run(transport="stdio")`, which cannot be accessed over a network. Only the parent process (e.g., Claude Desktop, Claude Code, OpenClaw) can communicate with it.
- **No authentication needed** — OS-level process isolation provides security. The parent process controls access.
- **API keys never returned** — `get_configuration` intentionally excludes API keys from its response.
- **Error messages sanitized** — No internal details, stack traces, or credentials in error responses.
- **Input validation** — All parameters have strict bounds and type checking.
- **Per-call settings overrides** — Settings overrides from tool parameters are in-memory only and not persisted.
- **`@no_db_settings`** — Prevents database settings access from MCP calls.

> **Security Note:** This MCP server is designed for **local use only**. Do not expose it over a network without implementing proper security controls (OAuth, rate limiting). See the [MCP Security Guide](https://modelcontextprotocol.io/docs/tutorials/security/security_best_practices) for network deployment requirements.

## Docker Deployment

The MCP server uses STDIO transport, which requires direct process communication with the host AI assistant (e.g., Claude Desktop). This means it **must run on the host machine**, not inside a Docker container.

- **MCP server** (`ldr-mcp`) — install and run on the **host** machine only
- **Web service** (`ldr-web`) — can run in Docker

The Docker image does not include MCP extras, and adding them would not help — the STDIO transport cannot bridge the container boundary to reach Claude Desktop.

## Usage Examples

### Prompt Patterns

**Quick fact-checking:**
```
Use quick_research to find: What is the current population of Tokyo?
```

**Deep analysis:**
```
Use detailed_research with focused-iteration strategy to analyze:
What are the latest advances in solid-state battery technology?
```

**Full report:**
```
Generate a report on the impact of AI on drug discovery using source-based strategy
```

**Document search:**
```
Search collection 'research-papers' for: machine learning optimization techniques
```

**Agentic research:**
```
Use the mcp strategy to research the environmental impact of cryptocurrency mining,
considering both proof-of-work and proof-of-stake systems
```

**Individual search engines (no LLM cost, fast):**
```
Search arxiv for recent papers on diffusion models
Search pubmed for CRISPR clinical trials 2024
Search wikipedia for quantum error correction
Search openclaw for copyright fair use precedents
```

The `search` tool is especially useful for **monitoring and subscriptions** — check for new content on a topic regularly without burning LLM tokens. An AI agent can call `search` to get raw results, then decide whether to run a full `detailed_research` only when something interesting appears.

### Tips

- Use `search` for fast, free lookups before committing to a full research run
- Start with `quick_research` to test your setup, then upgrade to `detailed_research` for depth
- Use `focused-iteration` strategy for highest accuracy on technical topics
- Lower temperature (0.3-0.5) for factual research, higher (0.8-1.2) for creative exploration (valid range: 0.0-2.0)
- Call `list_search_engines` and `list_strategies` first to see what's available in your configuration
- Use `get_configuration` to verify your LLM and search settings are correct

## Troubleshooting

| Problem | Solution |
|---------|----------|
| Server won't start | Verify MCP extras are installed: `pip install "local-deep-research[mcp]"` |
| "API key" errors | Check env vars in your Claude Desktop config (e.g., `LDR_LLM_OPENAI_API_KEY`) |
| "Invalid strategy" error | Run `list_strategies()` to see valid strategy names |
| "Unknown search engine" error | Run `list_search_engines()` to see available engines |
| No results returned | Try a different `search_engine` or make your query more specific |
| Server logs | Check stderr output. Log level is hardcoded to INFO. |

## Related Documentation

- [API Quickstart](api-quickstart.md) — HTTP and Python API access
- [Search Engines Guide](search-engines.md) — Available search engines and configuration
- [Configuration Reference](CONFIGURATION.md) — All LDR settings
- [Features Overview](features.md) — All LDR features
- [CLI Tools](cli-tools.md) — Command-line tools including `ldr-mcp`
