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"
}
}
}
}
```
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues