| """ |
| MCP Server for the contract analysis pipeline - this exposes the full LangGraph |
| pipeline as FastMCP tools so any MCP-compatible clients (Claude Desktop, Cursor, etc.) |
| can analyze contracts directly |
| |
| Tools: |
| - analyze_contract: run the pipeline on a raw contract string |
| - analyze_contract_file: run the pipeline on a local .txt file path |
| |
| Usage: |
| stdio transport, default for MCP clients: `python mcp_server.py` |
| HTTP transport, for testing in a browser/curl: `python mcp_server.py --transport http --port 8000` |
| |
| Prereqs: |
| - ANTHROPIC_API_KEY in .env or environment |
| - CUAD vector store built: python scripts/build_vector_store.py |
| """ |
|
|
| import json |
| import os |
|
|
| from dotenv import load_dotenv |
| from fastmcp import FastMCP |
|
|
| load_dotenv() |
|
|
| |
| mcp = FastMCP( |
| name="contract-analysis", |
| instructions=( |
| "Analyzes commercial contracts using a multi-agent AI pipeline. " |
| "Classifies clauses by CUAD type, scores risk, and benchmarks against " |
| "real contract examples. Returns a structured JSON report." |
| ), |
| ) |
|
|
| @mcp.tool() |
| def analyze_contract(contract_text: str) -> str: |
| """ |
| Run full contract analysis pipeline on a raw contract string. |
| All pipeline stages: ingestion -> knowledge graph -> classification -> risk analysis |
| -> benchmark -> report |
| |
| Args: contract_text - full text of contract to analyze |
| |
| Returns: |
| A JSON string containing the analysis report |
| """ |
| from agents.orchestrator_agent import run_pipeline |
|
|
| result = run_pipeline(contract_text) |
| return result.get("report", json.dumps({"error": "Pipeline returned no report"})) |
|
|
| @mcp.tool() |
| def analyze_contract_file(file_path: str) -> str: |
| """ |
| Run full contract analysis pipeline on a local .txt file |
| Reads file at given path & passes contents through the analysis pipeline (could |
| be useful when contract is stored on disk) |
| |
| Args: file_path - absolute or relative path to a .txt contract file. |
| |
| Returns: |
| A JSON string containing the analysis report (same format as analyze_contract) |
| Returns error JSON if file not found |
| """ |
| if not os.path.exists(file_path): |
| return json.dumps({"error": f"File not found: {file_path}"}) |
|
|
| with open(file_path, encoding="utf-8") as f: |
| contract_text = f.read() |
|
|
| from agents.orchestrator_agent import run_pipeline |
|
|
| result = run_pipeline(contract_text) |
| return result.get("report", json.dumps({"error": "Pipeline returned no report"})) |
|
|
| @mcp.resource("contract-analysis://pipeline-info") |
| def pipeline_info() -> str: |
| """ |
| Describe the contract analysis pipeline and its output schema. |
| Returns plain-text summary of what the pipeline does, what fields |
| each clause in the report contains |
| """ |
| return ( |
| "Contract Analysis Pipeline\n" |
| "==========================\n" |
| "Stages: ingestion -> knowledge_graph -> classification -> risk_analysis -> benchmark -> report\n\n" |
| "Output report fields per clause:\n" |
| " - id : clause index\n" |
| " - section : section header text\n" |
| " - clause_type : CUAD taxonomy label (41 types)\n" |
| " - confidence : classification confidence (0.0–1.0)\n" |
| " - risk_score : risk level (0.0 = low, 1.0 = high)\n" |
| " - risk_factors : list of identified risk factors\n" |
| " - benchmark_similarity: similarity to CUAD norms (0.0–1.0)\n" |
| " - benchmark_source : source CUAD contract(s) used\n" |
| " - text : first 200 chars of clause text\n\n" |
| "Summary fields:\n" |
| " - total_clauses : number of clauses analyzed\n" |
| " - entities_extracted : knowledge graph entity count\n" |
| " - relationships_extracted: knowledge graph relationship count\n" |
| " - graph_image_path : path to saved knowledge graph PNG\n" |
| ) |
|
|
| if __name__ == "__main__": |
| mcp.run() |
|
|