AI-assisted contract review. Upload a legal document (PDF or TXT) and get a structured analysis: document type, plain-English summary, important clauses, legal risks with a 0–100 risk score, key deadlines, and recommended follow-up tasks.
Three services:
- web — Next.js 16 + React 19 + HeroUI v3 (Tailwind v4) frontend and API routes.
- mcp — a Python Model Context Protocol
server exposing an
analyze_documenttool that calls Claude (claude-opus-4-8) with structured outputs. - db — PostgreSQL, storing each analysis (full result as JSONB).
Browser → /api/analyze (web) → MCP client → MCP server → Claude
│ │
└────────────── Postgres ◄───────── structured result
- A Claude API key from https://console.claude.com (
ANTHROPIC_API_KEY). - Either Docker (recommended), or Node 22+, pnpm 11.9.0, Python 3.12+, and uv for local development.
cp .env.example .env # then edit .env and set a real ANTHROPIC_API_KEY
docker compose up --buildOpen http://localhost:3000. Docker Compose reads .env automatically for the
ANTHROPIC_API_KEY substitution, builds the web and MCP images, and starts
Postgres with the schema in docker/init.sql applied on first run.
Run Postgres in Docker, and the web + MCP servers natively:
# 1. Environment
cp .env.example .env # set ANTHROPIC_API_KEY
# 2. Database
docker compose up -d db
# 3. MCP server (terminal A)
cd mcp
uv sync
uv run --env-file ../.env python src/legal_server.py # http://localhost:8000
# 4. Web app (terminal B)
pnpm install
pnpm dev # http://localhost:3000The MCP server is a separate process and must be running for analysis to work; if it is down, the UI shows "Analysis failed. Is the MCP server running?".
| Variable | Used by | Example |
|---|---|---|
ANTHROPIC_API_KEY |
mcp | sk-ant-... |
DATABASE_URL |
web | postgresql://postgres:postgres@localhost:5432/legal_analyzer |
MCP_SERVER_URL |
web | http://localhost:8000 |
In Docker Compose, DATABASE_URL and MCP_SERVER_URL are set automatically;
only ANTHROPIC_API_KEY needs to be in .env. Without DATABASE_URL, the app
still analyzes documents — it just skips persistence.
- Open http://localhost:3000.
- Drag in (or choose) a contract as PDF or TXT.
- Click Analyze Document. PDFs are read natively by Claude; analysis takes ~15–60s depending on length.
- Review the summary, risk score, clauses, deadlines, and follow-up tasks.
Each analysis is saved;
GET /api/caseslists past analyses.
app/ Next.js App Router pages + API routes (/api/analyze, /api/cases)
components/ UI components (upload, summary, risk, clauses, deadlines, tasks)
lib/ types, Postgres client (db.ts), MCP client (mcp.ts)
mcp/ Python MCP server (src/legal_server.py)
docker/ Dockerfiles + Postgres init.sql
docs/ Project documentation