Skip to main content
Glama
rajmodi262

Keystone MCP Server

by rajmodi262
README.md
<div align="center">

# ๐Ÿ›๏ธ Keystone

### AEC Project & Document Intelligence Platform

**Construction documents constantly contradict each other โ€” one spec says 30 MPa concrete, a drawing says 25.
Keystone is the lighttable that catches it.** It reads across every spec, drawing, and RFI to surface
contradictions other tools hide, and maps the *blast radius* of every revision before it reaches the site.

`TypeScript` ยท `Next.js 14` ยท `tRPC` ยท `Prisma` ยท `PostgreSQL + pgvector` ยท `Tailwind` ยท `Docker` ยท `MCP`

</div>

<div align="center">

![Impact graph โ€” blast radius](docs/screenshots/03-impact-graph.png)

<sub>The impact graph: revise a document and the blast radius propagates outward โ€” affected drawings and RFIs in amber, the contradiction in red.</sub>

![Conflict-aware answer](docs/screenshots/04-conflict-ask.png)

<sub>Ask across the project and Keystone returns the contradiction (30 MPa vs 25 MPa) with both sources โ€” not a single confident answer.</sub>

</div>

---

## The idea

Most AEC document tools are passive file cabinets with a search box. On a real project, dozens of people
work off the same documents, and two things constantly go wrong:

1. **Documents contradict each other** and nobody notices until it's expensive.
2. **A revision quietly makes other documents stale** โ€” and no one gets told.

Generic RAG makes #1 *worse*: it returns one confident answer from the top-matching chunk, even when
another document disagrees. Keystone does two things differently.

### 1. Conflict-aware RAG
Ask *"what concrete strength is required?"* and instead of one answer, Keystone retrieves the evidence,
clusters the claims, and โ€” if sources disagree โ€” returns the **contradiction**:

> โš ๏ธ **Conflict** โ€” `03 30 00` (Rev C) says **30 MPa**, `S-201` (Rev A) says **25 MPa**.

In construction, the disagreement *is* the answer worth knowing.

### 2. Change-impact graph ("blast radius")
Every document references others (`S-201` โ†’ "per Spec `03 30 00`"). Keystone extracts those references
into a dependency graph. Revise one document and it traces the blast radius โ€” every drawing and RFI
downstream that just became suspect โ€” and animates it outward from the epicentre.

Both are tractable because AEC documents use **rigid identifiers** (CSI MasterFormat codes like
`03 30 00`, sheet numbers like `S-201`), so reference extraction is deterministic, not guesswork.

---

## Stack

| Layer | Tech |
|------|------|
| Frontend | Next.js 14 (App Router), React 18, **TypeScript**, Tailwind CSS |
| API | **tRPC** (end-to-end typesafe), Zod |
| Data | **Prisma** ORM, **PostgreSQL 16 + pgvector** |
| Auth | NextAuth (credentials + JWT), bcrypt, multi-tenant **RBAC** |
| AI | RAG over pgvector embeddings; conflict-aware retrieval; **MCP server** |
| DevOps | **Docker**, GitHub Actions CI, **DigitalOcean** App Platform |

> Runs with **zero API keys** โ€” a deterministic local embedder backs the AI layer out of the box.
> Set `OPENAI_API_KEY` (or any OpenAI-compatible base URL) to swap in a real provider.

---

## Quick start

```bash
npm install
cp .env.example .env          # defaults work for local Docker
npm run db:up                 # Postgres + pgvector in Docker
npm run db:migrate            # create schema
npm run db:seed               # demo project with a planted conflict
npm run dev                   # http://localhost:3000
```

Sign in with the seeded account: **demo@keystone.dev** / **password123**, then open
*Riverside Hospital โ€” Phase 2*.

---

## Features

- **Multi-tenant workspaces** โ€” organizations, members, role-based access (Owner / Architect / Engineer / Contractor / Client)
- **Documents** โ€” drawings, specs, and RFIs; chunked, embedded into pgvector, cross-referenced into a graph
- **Impact graph** โ€” interactive blast-radius visualization; click any document to trace what it affects
- **Conflict detection** โ€” flags graph-adjacent documents that assert different values for the same unit
- **Ask your project** โ€” conflict-aware Q&A with citations
- **MCP server** โ€” exposes project tools (`ask_project`, `search_documents`, `list_conflicts`, โ€ฆ) to any MCP client

---

## MCP

```bash
npm run mcp        # stdio server for Claude Desktop / MCP clients
npm run mcp:test   # in-process smoke test
```

See [`mcp/README.md`](mcp/README.md) for the Claude Desktop config.

---

## Deploy

- **CI** โ€” `.github/workflows/ci.yml` runs typecheck, lint, and build on every push.
- **Docker** โ€” `docker build -t keystone .` produces a standalone production image.
- **DigitalOcean** โ€” `doctl apps create --spec .do/app.yaml` provisions the web service + managed
  Postgres and runs `prisma migrate deploy` as a pre-deploy job. (Enable the `vector` extension on the
  managed database.)

---

## Project structure

```
src/
  app/                 # routes: landing, auth, /app dashboard, /app/projects/[id]
  components/          # providers, auth shell, workspace (impact graph, ask, conflicts)
  server/
    routers/           # tRPC routers: auth, projects, documents, conflicts, ai
    services/          # ingest, conflict detection, conflict-aware ask
    lib/               # access control (RBAC)
  lib/                 # db, ai (embeddings + LLM), chunking, reference extraction, claims
prisma/                # schema + seed
mcp/                   # Model Context Protocol server
design/                # the "Lighttable" interactive prototype
```