Skip to main content
Glama
README.md
# LineSight

**An MCP server that turns plant-floor data into continuous-improvement insight.**

LineSight gives an AI assistant the same toolkit a CI engineer carries onto the
shop floor — OEE math, downtime Pareto analysis, SPC control charts, and
yield-loss dollars — exposed through Anthropic's
[Model Context Protocol](https://modelcontextprotocol.io). Ask it *"why is
line-3 slowing down?"* and it doesn't guess: it pulls the control chart, finds
the Western Electric violations, checks the downtime log, and answers with
evidence.

Built by a CI/OE practitioner ([marcoaguzmanjr.com](https://www.marcoaguzmanjr.com))
to bring the DMAIC discipline of the factory floor to AI tooling: every number
the model reports traces back to a formula in
[plant/analytics.py](plant/analytics.py).

---

## What you can ask it

```
> /daily_huddle line-1          # 3-minute tier-1 meeting brief, built from live data
> /dmaic line-2                 # full Define-Measure-Analyze-Improve-Control investigation
> /a3_report line-3             # one-page A3 problem-solving report
> why is @line-3 slowing down?  # @-mention a line to inject its KPI snapshot
> which shift on line-2 has the quality problem, and what is it costing us per year?
```

The kind of exchange this produces (every number below is what the tools
actually return on the demo dataset):

> **You:** which shift on line-2 has the quality problem?
>
> **Claude:** *(calls `get_oee` with `line_id=line-2, group_by=shift`)*
> Shift C. Its quality rate is 96.8% vs ~98.8% on shifts A and B — roughly
> 3× the scrap. *(calls `get_yield_loss`)* At standard cost that's about
> **$480K annualized** across the line, with shift C driving the majority.
> Worth checking what's different on C: staffing, changeover timing, or
> equipment settings that drift outside day-shift support hours.

## The three MCP primitives, applied

| Primitive | What LineSight exposes |
|---|---|
| **Tools** (model-controlled) | `get_oee` · `pareto_downtime` · `spc_analysis` · `get_yield_loss` · `log_action` · `list_actions` · `close_action` |
| **Resources** (app-controlled) | `plant://overview` · `plant://lines` · `plant://lines/{id}` KPI snapshots · `plant://reason-codes` |
| **Prompts** (user-controlled) | `/daily_huddle` · `/dmaic` · `/a3_report` |

The split matters: analysis lives in **tools** so the model can chain them
freely; context the *user* chooses to bring in (an @-mentioned line) comes from
**resources**; and multi-step CI rituals with a defined shape (a DMAIC, an A3)
ship as **prompts** so they run the same way every time.

```mermaid
flowchart LR
    U[You] --> CLI[Chat CLI<br/>prompt-toolkit]
    CLI --> C[Claude<br/>Anthropic API]
    C <-->|MCP stdio| S[LineSight MCP server<br/>FastMCP]
    S --> A[analytics.py<br/>OEE · Pareto · SPC · yield $]
    A --> D[(production_log.csv<br/>downtime_log.csv)]
    S --> R[(action_register.json)]
```

## The demo dataset tells a story

`data/` holds 90 days of seeded, reproducible shift-level records for a
three-line condiment plant (810 production records, ~2,300 downtime events).
Three problems are hidden in it — the same patterns you'd hunt for in a real
plant:

1. **line-2 bleeds availability to changeovers** — one reason code carries
   ~52% of all downtime minutes. A Pareto finds it instantly.
2. **line-2, shift C has a quality problem** — scrap runs ~3× the other
   shifts (cap-seal torque drift). Invisible in the line-level average;
   obvious the moment you group by shift.
3. **line-3 is degrading, not broken** — filler-head bearing wear drags
   performance down over the final three weeks. No single bad day; the SPC
   chart catches the run below center line and the cascade of below-LCL
   points that a "top losses yesterday" report would miss.

Regenerate identical data anytime: `python -m plant.data_gen` (seeded).

## Quick start

Requires Python 3.10+ and an [Anthropic API key](https://console.anthropic.com).

```bash
git clone https://github.com/marcoaguzman/linesight.git && cd linesight
python3 -m venv .venv && source .venv/bin/activate
pip install "anthropic>=0.51.0" "mcp[cli]>=1.8.0" "prompt-toolkit>=3.0.51" "python-dotenv>=1.1.0"
cp .env.example .env      # then add your ANTHROPIC_API_KEY
python main.py
```

Or with [uv](https://docs.astral.sh/uv/): `uv sync`, set `USE_UV=1` in `.env`,
then `uv run main.py`.

### Verify without an API key

The smoke test drives every tool, resource, and prompt over a real MCP stdio
connection — no Anthropic key needed:

```bash
python scripts/smoke_test.py     # 18 checks, should all PASS
```

### Use it from Claude Desktop instead

LineSight is a standard MCP server, so any MCP client can host it. For Claude
Desktop, add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "linesight": {
      "command": "/absolute/path/to/linesight/.venv/bin/python",
      "args": ["/absolute/path/to/linesight/mcp_server.py"]
    }
  }
}
```

## Project structure

```
linesight/
├── mcp_server.py        # the MCP server: 7 tools, 4 resources, 3 prompts
├── mcp_client.py        # generic MCP stdio client
├── main.py              # chat CLI entry point
├── core/                # chat loop, Claude wrapper, tool dispatch, terminal UI
├── plant/
│   ├── analytics.py     # OEE, Pareto, XmR control charts, yield-loss math
│   ├── store.py         # CSV-backed data layer (swap for a historian/MES)
│   └── data_gen.py      # seeded demo-data generator
├── data/                # the demo dataset (committed, reproducible)
└── scripts/smoke_test.py
```

Swapping the demo CSVs for a real historian or MES connection only touches
`plant/store.py` — the MCP surface stays identical.

## Credits

The chat-client scaffolding (`core/`, `mcp_client.py`) is adapted from the
project built in [Anthropic's MCP course](https://anthropic.skilljar.com/introduction-to-model-context-protocol);
the plant domain — server, analytics, dataset — is original work.