Skip to main content
Glama
README.md
# Perplexity Full MCP

An MCP server that gives AI agents **live research** and **image generation** capabilities by automating a logged-in Perplexity Pro browser session.

No API keys needed. No rate limits. Just a browser with your Pro account.

---

## What It Does

Two tools for any MCP client (Claude Code, Cline, Continue, Hermes Agent, etc.):

| Tool | What it returns |
|------|----------------|
| `perplexity_research(query)` | Answer text + list of source citations |
| `perplexity_generate_image(prompt)` | Image URL + local file path + dimensions |

The tools require **zero setup after first login** — just configure, log in once, and use.

---

## How It Works

```
Your AI Agent → MCP Client → perplexity-mcp (Python)
                                  │
                          ┌───────┴───────┐
                          │  Playwright    │
                          │  launches      │
                          │  Chromium      │
                          │  headless      │
                          └───────┬───────┘
                                  │
                          Navigates to perplexity.ai
                          Loads saved session cookies
                          Types your query into #ask-input
                          Presses Enter
                                  │
                    ┌─────────────┴─────────────┐
                    │ research                  │ image_gen
                    │                           │
              Waits for "Stop"            Waits for <img>
              button → disappeared        from S3 bucket
              Extracts answer text         Downloads image
              + citations links            Saves to disk
                    │                           │
                    └─────────────┬─────────────┘
                                  │
                          Returns result dict
                          Closes browser (ephemeral)
```

Each tool call is **isolated** — a fresh Chromium launches, does its work, and closes. Nothing persists in memory between calls.

---

## Requirements

- **Python** 3.10+
- **Perplexity Pro** account
- **Chromium** browser installed on your system

---

## Quick Install

```bash
# 1. Get the code
git clone <repo-url> perplexity-mcp
cd perplexity-mcp

# 2. Create virtual environment & install dependencies
python3 -m venv .venv
.venv/bin/pip install -e .

# 3. Verify Chromium is available
which chromium-browser || which google-chrome || echo "Need Chromium"
```

---

## Setup Guide

### Step 1 — Install dependencies

```bash
cd perplexity-mcp
python3 -m venv .venv
.venv/bin/pip install -e .
```

This installs: FastMCP, Playwright, Pillow, httpx, python-slugify, python-dotenv, and playwright-stealth.

### Step 2 — Find your Chromium

The server auto-detects Chromium from these sources (checked in order):

1. `PLAYWRIGHT_CHROMIUM_PATH` environment variable (if set)
2. Snap path: `/snap/chromium/current/usr/lib/chromium-browser/chrome`
3. Default Playwright browser (if you ran `playwright install chromium`)

If auto-detection fails, set the path manually:

```bash
export PLAYWRIGHT_CHROMIUM_PATH=/usr/bin/chromium-browser
```

To verify everything is working:

```bash
.venv/bin/python -c "
import asyncio
from playwright.async_api import async_playwright
from config import SYSTEM_CHROMIUM
async def t():
    async with async_playwright() as p:
        b = await p.chromium.launch(headless=True, executable_path=SYSTEM_CHROMIUM)
        page = await (await b.new_context()).new_page()
        await page.goto('https://example.com')
        print('Chromium works! Title:', await page.title())
        await b.close()
asyncio.run(t())
"
```

### Step 3 — (Optional) Configure image output directory

Edit `.env` or set the environment variable:

```
OUTPUT_ROOT=~/Pictures/perplexityImages
```

### Step 4 — Start the server

```bash
.venv/bin/perplexity-mcp
```

This starts the MCP server on stdio. It will check for saved cookies and either skip to ready state or prompt you to log in.

---

## MCP Client Configuration

### Claude Code / Cline / Continue

Add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "perplexity": {
      "command": "/absolute/path/to/perplexity-mcp/.venv/bin/perplexity-mcp",
      "args": [],
      "env": {
        "OUTPUT_ROOT": "/home/youruser/Pictures/perplexityImages"
      }
    }
  }
}
```

### Hermes Agent

Add to `~/.hermes/config.yaml`:

```yaml
mcp_servers:
  perplexity:
    command: "/absolute/path/to/perplexity-mcp/.venv/bin/perplexity-mcp"
    args: []
    env:
      DISPLAY: ":0"
      OUTPUT_ROOT: "/home/youruser/Pictures/perplexityImages"
    supports_parallel_tool_calls: true
```

Or via CLI:

```bash
hermes mcp add perplexity \
  --command "/absolute/path/to/perplexity-mcp/.venv/bin/perplexity-mcp" \
  --env "DISPLAY=:0" \
  --env "OUTPUT_ROOT=/home/youruser/Pictures/perplexityImages"
```

Then run `/reload-mcp` in your Hermes session.

> **⚠️ DISPLAY note:** If Chromium doesn't appear on your screen during login, your MCP client isn't forwarding the `DISPLAY` environment variable to subprocesses. Always include `DISPLAY: ":0"` in the `env` section. Find your display value with `echo $DISPLAY`.

---

## First-Time Login

The first time the server connects to Perplexity, it opens a **visible Chromium window**.

**What you'll see:**

```
============================================================
  Perplexity Login Required
============================================================
  A browser window will open. Please log in to your
  Perplexity Pro account.
============================================================
```

**What to do:**

1. A Chromium window opens to `perplexity.ai`
2. Log in with your Perplexity Pro credentials
3. If prompted with a Cloudflare CAPTCHA, solve it
4. **If running in a terminal** — go back to the terminal and press Enter
5. **If running under an MCP client** — just close the browser after logging in. The server detects the login automatically within 2 minutes and saves cookies

After successful login, your session cookies are saved to `storage/perplexity_auth.json`. All subsequent tool calls run **headless** — no visible windows.

---

## Using the Tools

Once the server is running and authenticated, your AI agent has access to both tools.

### perplexity_research

Ask the agent to research a topic:

```
Can you research the latest breakthroughs in solid-state batteries?
```

**What happens:** Chromium launches headless → types your query into Perplexity → waits for the answer to finish generating → extracts the markdown answer and all citation links → closes browser → returns to your agent.

**Result:** The agent receives the answer text plus up to 30 source citations with titles and URLs.

### perplexity_generate_image

Ask the agent to create an image:

```
Generate a photorealistic cyberpunk city at night with neon lights and rain.
```

**What happens:** Chromium launches headless → types your prompt → waits for the image to appear (30-120s) → downloads it from Perplexity's S3 → saves it to your configured output directory → returns the file path.

**Result:** The agent gets the file path, image dimensions, and a temporary URL. The image is saved to disk at the configured `OUTPUT_ROOT`.

---

## Configuration Reference

| Env Variable | Default | Description |
|-------------|---------|-------------|
| `OUTPUT_ROOT` | `~/Pictures/perplexityImages` | Base directory for generated images |
| `PLAYWRIGHT_CHROMIUM_PATH` | Auto-detect snap | Custom Chromium/Chrome executable path |

### Image path pattern

```
{OUTPUT_ROOT}/{first-3-words-slugified}/{full-prompt-slugified}_{timestamp}.{ext}
```

Example: prompt `"a cute cat wearing a funny hat"` → `/home/user/Pictures/perplexityImages/a-cute-cat/a-cute-cat-wearing-a-funny-hat_2026-06-28-143022.png`

If a file already exists, a counter suffix is appended (`_1`, `_2`, ...). No files are ever overwritten.

---

## Troubleshooting

| Problem | Likely cause | Fix |
|---------|-------------|-----|
| `ModuleNotFoundError` | Dependencies not installed | Run `.venv/bin/pip install -e .` |
| Chromium window doesn't appear | `DISPLAY` not forwarded | Add `DISPLAY: ":0"` to MCP client env config |
| "Perplexity session expired" | Cookies invalidated | Delete `storage/perplexity_auth.json` and restart |
| Tool times out (Cloudflare) | Cloudflare CAPTCHA challenge | The server auto-detects it, opens a headed browser for you to solve, saves the clearance cookie, and retries |
| Tool times out (slow Perplexity) | Perplexity server slow | Run the tool again |
| "can't generate images" | Region restriction | Perplexity blocks image gen in some countries |
| "Image generation failed" | Timeout after 3 minutes | Try a simpler prompt. Generation takes 30-120s normally |
| Tools return empty results | Perplexity UI changed | The DOM selectors may need updating |

---

## Tools Reference

### `perplexity_research(query: str) -> dict`

| Field | Type | Description |
|-------|------|-------------|
| `answer` | `string` | Markdown answer text from Perplexity |
| `citations` | `array` | List of `{title, url}` objects (max 30) |

**Agent best practices:**
- Be specific: *"What are the economic impacts of AI on healthcare in 2026?"* not *"Tell me about AI"*
- Inline citation markers `[1]`, `[2]` appear in the answer text
- Break complex multi-part questions into separate calls
- Citations are from the Answer tab panel on Perplexity

### `perplexity_generate_image(prompt: str) -> dict`

| Field | Type | Description |
|-------|------|-------------|
| `url` | `string` | Temporary S3 URL for the generated image |
| `alt` | `string` | Auto-generated alt text |
| `file_path` | `string` | Absolute path to the saved image on disk |
| `width` | `int` | Image width in pixels |
| `height` | `int` | Image height in pixels |

**Agent best practices:**
- Describe subject, style, lighting, colors, composition
- *"A serene Japanese garden in spring with cherry blossoms, koi pond, digital art"* > *"a garden"*
- Reference `file_path` to use the image (URL may expire)
- Generation takes 30-120 seconds
- On failure, retries once automatically

---

## Project Structure

```
perplexity-mcp/
├── pyproject.toml          # Python package config + dependencies
├── .env                    # OUTPUT_ROOT config (user-specific, gitignored)
├── .gitignore
├── README.md
├── config.py               # Paths, env vars, Chromium auto-detection
├── browser.py              # Playwright manager: launch, stealth, auth, cookie persist
├── server.py               # FastMCP server with lifespan lifecycle
└── tools/
    ├── research.py         # Type query → wait for stop → extract answer + citations
    └── image_gen.py        # Type prompt → detect S3 img → download → save to disk
```

Runtime files (created on first use):

```
storage/perplexity_auth.json        # Playwright session cookies (gitignored)
~/Pictures/perplexityImages/        # Generated images (configurable via OUTPUT_ROOT)
```

---

## Tech Stack

| Component | Library | Purpose |
|-----------|---------|---------|
| MCP framework | **FastMCP** 3.x | Server lifecycle, tool registration, stdio transport |
| Browser automation | **Playwright** | Launch Chromium, navigate, interact with DOM |
| Anti-detection | **playwright-stealth** | Mask automation fingerprints from Cloudflare |
| Image processing | **Pillow** | Extract width/height from saved images |
| HTTP | **httpx** | Download images from S3 |
| Filename generation | **python-slugify** | Convert prompts to filesystem-safe paths |
| Config | **python-dotenv** | Load `.env` file |

---

## For AI Agents

When using these tools in your workflow:

1. **Research first, generate second** — research gives context for better image prompts
2. **Run them in parallel** — `supports_parallel_tool_calls: true` is set in Hermes config
3. **Reference `file_path` for images** — the URL may expire, but the local file persists
4. **Catch errors gracefully** — session expiry, region blocks, and timeouts all raise typed errors
5. **Tools are ephemeral** — each call opens and closes Chromium (~3-5s overhead)