Skip to main content
Glama
palash018

Phabricator MCP Server

by palash018
README.md
# Phabricator MCP Server

Standalone MCP server for Phabricator, kept outside the devel repo so hg stays clean.

## Setup

1. Copy env file and fill credentials:
   ```bash
   cp .env.example .env
   # Edit .env with your Phabricator API token
   ```

2. Install deps (already done in `venv`):
   ```bash
   python3 -m venv venv
   ./venv/bin/pip install mcp requests python-dotenv
   ```

## Run

```bash
./run.sh
```

Or manually:
```bash
source venv/bin/activate
python3 server.py
```

## Tools exposed

### Phabricator API
- `search_tasks` – query tasks by status / priority / assigned / text
- `get_task` – fetch a single task by ID with full description, media, and comments
- `get_task_comments` – fetch only comments / transactions for a task
- `create_task` – create a new maniphest task
- `edit_task` – update an existing task or add a comment
- `search_revisions` – search differential revisions
- `get_revision` – fetch a revision by ID
- `get_revision_diff` – fetch raw diff for a revision
- `get_unbreak_tasks` – list open unbreak tasks
- `get_projects` – search Phab projects
- `get_project_members` – list members of a project
- `search_users` – search Phab users
- `get_file_info` – get metadata for a file / image by PHID
- `query_phids` – resolve arbitrary PHIDs to objects
- `ping` – health-check connectivity

### RAG (Semantic Search)
- `phab_search_rag` – semantic search over indexed tasks and revisions
- `phab_ask` – natural-language Q&A with source attribution

## RAG Architecture

```
Phabricator API                    ChromaDB Vector Store
     │                                      ▲
     ▼                                      │
┌─────────────┐    ┌─────────────┐    ┌──────────┐
│  Extractor  │───▶│   Chunker   │───▶│ Indexer  │
│  (Conduit)  │    │ (tiktoken)  │    │(metadata)│
└─────────────┘    └─────────────┘    └──────────┘
                                            ▲
┌─────────────┐    ┌─────────────┐          │
│ Diff Parser │───▶│  Embedder   │──────────┘
│(files/hunks)│    │(OpenAI 3-sm)│
└─────────────┘    └─────────────┘

Query Flow:
┌──────────┐    ┌──────────┐    ┌─────────┐    ┌──────────┐
│  User    │───▶│ Embedder │───▶│  Search │───▶│  LLM     │
│  Query   │    │ (OpenAI) │    │(ChromaDB)│    │(Anthropic│
└──────────┘    └──────────┘    └─────────┘    │ Claude)  │
                                                └──────────┘
```

### Tech Stack
- **Embeddings:** OpenAI `text-embedding-3-small` (1536 dims)
- **Vector DB:** ChromaDB with cosine similarity + metadata filtering
- **LLM:** Anthropic Claude Haiku for RAG synthesis
- **Chunking:** tiktoken-based with 512-token chunks, 50-token overlap
- **Diff Metadata:** Files changed, hunk context lines (function/class names)

## RAG Setup

1. **Add API keys to `.env`:**
   ```bash
   OPENAI_API_KEY=sk-...          # Required for embeddings
   ANTHROPIC_API_KEY=sk-ant-...   # Required for RAG Q&A
   ```

2. **Run the full index (one-time):**
   ```bash
   source venv/bin/activate
   python scripts/full_index.py
   ```
   - ~47K tasks + ~38K revisions = ~116M tokens
   - Cost: ~$2.32 (OpenAI embeddings)
   - Time: ~16 hours (fast mode) or ~30 hours (full mode)

3. **Fast mode (recommended for first run):**
   ```bash
   python scripts/full_index.py --skip-comments --skip-diffs
   ```
   - Indexes titles, descriptions, summaries only
   - ~4–6x faster than full mode
   - Resume capability: re-run without flags later to enrich with comments/diffs

4. **Test a subset first:**
   ```bash
   python scripts/full_index.py --task-limit 10 --rev-limit 10
   ```

## Incremental Sync

After the initial index, run incremental sync to pick up new and modified tasks/revisions:

```bash
python scripts/incremental_sync.py
```

This fetches only objects modified since the last sync (stored in `last_sync.json`) and updates the vector store. Use `--dry-run` to preview what would be synced without making changes.

### Cron setup (daily sync)
```bash
# Add to crontab (crontab -e)
# Replace /path/to/mcp-phab with your project directory
0 2 * * * cd /path/to/mcp-phab && venv/bin/python scripts/incremental_sync.py >> /tmp/phab_sync.log 2>&1
```

## RAG Usage

### Via MCP Tools
```
phab_search_rag(query="find bugs about email signups", limit=5)
phab_ask(query="What caused the AttributeError in matching filters?")
```

### Via CLI (direct Python)
```bash
python -c "
from rag.embedder import Embedder
from rag.indexer import Indexer
emb = Embedder()
idx = Indexer()
results = idx.search(emb.embed(['email signup bugs'])[0], limit=3)
for r in results:
    print(r['metadata']['source_uri'], r['metadata']['title'])
"
```

## Claude Desktop config

Add to your Claude Desktop MCP settings (`~/.config/claude/mcp-config.json` or similar).
Replace `/path/to/mcp-phab` with your actual project directory and fill in your credentials:

```json
{
  "mcpServers": {
    "phab": {
      "command": "/path/to/mcp-phab/venv/bin/python3",
      "args": ["/path/to/mcp-phab/server.py"],
      "env": {
        "PHABRICATOR_URL": "https://phabricator.example.com",
        "PHABRICATOR_API_TOKEN": "your-api-token-here",
        "TRANSPORT": "stdio"
      }
    }
  }
}
```