legal-contract-mcp
# legal-contract-mcp
[](https://github.com/Rajasrikondaveeti/legal-contract-mcp/actions/workflows/ci.yml)
An MCP (Model Context Protocol) server that gives an LLM client (Claude, Claude Code, Claude Desktop, etc.) tools to do a first-pass review of contracts: load a `.txt`/`.docx`/`.pdf`, detect standard clause types, flag heuristic risk issues, generate a summary, and diff two contracts against each other.
This is **not legal advice** — it's a rules-based first pass meant to speed up human review, built to demonstrate a real, non-trivial MCP server (as opposed to a toy "add two numbers" example).
## Why this exists
Most MCP server examples are thin wrappers around an API call. This one does actual work locally:
- Parses real document formats (txt/docx/pdf)
- Detects 12 standard clause types via a maintained pattern library, not a single regex
- Runs 8 explainable risk heuristics (e.g. indemnification without a liability cap, auto-renewal without a clear notice period, non-competes with no defined scope) — every flag cites the exact clause text it's based on
- Falls back gracefully to an extractive summary if no ` OPENAI_API_KEY` is set, and upgrades to an LLM-generated summary if one is
## Tools exposed
| Tool | Description |
|---|---|
| `load_contract(path)` | Load a `.txt`/`.docx`/`.pdf` file, returns a `doc_id` |
| `list_documents()` | List contracts loaded in this session |
| `extract_clauses(doc_id)` | Detected clause types with snippets |
| `missing_clauses(doc_id)` | Standard clause types NOT found — gap check |
| `flag_risks(doc_id)` | Heuristic risk flags with severity + evidence |
| `summarize_contract(doc_id)` | Plain-English summary (LLM or extractive fallback) |
| `compare_contracts(doc_id_a, doc_id_b)` | Diff clause types and risk flags between two contracts |
| `search_clause_library(query)` | Look up a clause type's definition by keyword |
## Setup
```bash
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
```
Optional — enable LLM-powered summaries:
```bash
export OPENAI_API_KEY=sk-ant-...
```
## Run it
**Inspector (interactive dev UI):**
```bash
mcp dev src/legal_contract_mcp/server.py
```
**As a stdio server** (for Claude Desktop / Claude Code config):
```json
{
"mcpServers": {
"legal-contract-mcp": {
"command": "python",
"args": ["-m", "legal_contract_mcp.server"],
"cwd": "/absolute/path/to/legal-contract-mcp",
"env": { "OPENAI_API_KEY": "sk-ant-..." }
}
}
}
```
Then in a chat with the connected client:
> Load the contract at tests/sample_contracts/weak_nda.txt and flag its risks.
## Test
```bash
pytest # unit tests for clause detection + risk rules
python scripts/smoke_test.py # spins up the real MCP server over stdio and calls every tool
```
Includes two sample contracts (`tests/sample_contracts/weak_nda.txt` and `solid_msa.txt`) chosen so the risk engine's output differs meaningfully between a weak and a well-drafted agreement — tests assert on that difference, not just "does it run."
## Project structure
```
src/legal_contract_mcp/
parsing.py # txt/docx/pdf -> plain text, in-memory doc store
clause_library.py # 12 clause types: definitions + detection patterns
clauses.py # runs the library against a document
risk_rules.py # 8 heuristic risk rules, each with cited evidence
llm.py # optional Claude-powered summary, extractive fallback
server.py # FastMCP tool definitions
tests/
sample_contracts/ # weak NDA vs. solid MSA fixtures
test_clauses_and_risks.py
```
## Extending it
- Add a clause type: add an entry to `CLAUSE_LIBRARY` in `clause_library.py` with a definition and one or more regex patterns.
- Add a risk rule: add a function block to `evaluate_risks()` in `risk_rules.py` — return a `RiskFlag` with `rule`, `severity`, `message`, and `evidence`.
- Swap the in-memory store in `parsing.py` for a database if you want documents to persist across server restarts.
## Disclaimer
This tool provides automated, heuristic pattern-matching only. It is not a substitute for review by a licensed attorney and should not be relied on as legal advice.
TDQS
Scored across 8 tools
Each tool has a clearly distinct purpose: loading, listing, extracting clauses, flagging risks, summarizing, comparing, gap analysis, and library search. There is no meaningful overlap between tool responsibilities.
Most tools follow a consistent snake_case verb_noun pattern like load_contract, extract_clauses, and compare_contracts. The one minor deviation is missing_clauses, which is not in an imperative verb form.
With 8 tools, the server is well-scoped for contract analysis. Each tool covers a distinct part of the workflow without redundancy or bloat.
The core analysis workflow is well covered: load, extract, flag, summarize, compare, and check missing clauses. Minor gaps exist such as no tool for unloading documents or retrieving raw full contract text, but agents can work around these.