Skip to main content
Glama
README.md
# IVR Flow Linter

![Build Status](https://github.com/rafareses/ivr-flow-linter/actions/workflows/ci.yml/badge.svg)
![Python Version](https://img.shields.io/badge/python-3.11-blue.svg)
![License](https://img.shields.io/badge/license-MIT-green.svg)

**Deterministic IVR Flow Linter via MCP + ChatGPT Skybridge Widget**

A Model Context Protocol (MCP) server that validates IVR flows (JSON) providing a score, error detection (unreachable nodes, dead ends), and suggested fixes. Includes a Skybridge-pattern HTML widget for visualizing results directly in ChatGPT.

[Demo Video](assets/demo_video.webp)

![Widget Screenshot](assets/widget_screenshot.png)

## Features

- **Strict Validations**: Unreachable nodes, dead ends, missing fallbacks, undefined variables.
- **Best Practices**: Warning on long prompts, multiple questions, and irreversible actions without confirmation.
- **Idempotency**: Consistent results via flow hashing.
- **Skybridge Widget**: Interactive HTML/JS visualization with zero external dependencies.
- **MCP Compatible**: Works with both ChatGPT Actions and Claude Desktop.

## Architecture

- **Server**: FastAPI with JSON-RPC 2.0 (`/mcp`)
- **Linter**: Pure Python deterministic engine
- **Widget**: Inline HTML injection (text/html+skybridge)

## Local Development

### Prerequisites
- Python 3.9+
- git

### Setup
```bash
# Clone
git clone https://github.com/arebury/ivr-flow-linter.git
cd ivr-flow-linter

# Virtual Environment
python -m venv venv
source venv/bin/activate

# Install
pip install -r requirements.txt

# Run Server
uvicorn src.main:app --host 0.0.0.0 --port 8000 --reload
```
Visit `http://localhost:8000/demo` for an interactive simulator.

### Validating the Demo
1. Run server: `uvicorn src.main:app --host 0.0.0.0 --port 8000 --reload`
2. Open `http://localhost:8000/demo`
3. Select "Invalid: Dead End" from the dropdown.
4. Click **Lint & Render**.
5. Verify:
   - "Parsed Result" tab shows errors.
   - Widget renders the flow with error indicators.

## Deployment (Render)

This project includes a `render.yaml` for 1-click deployment on Render.

1. Create a new **Web Service** on [Render](https://render.com).
2. Connect your GitHub repository: `https://github.com/arebury/ivr-flow-linter`.
3. Select "Python 3" runtime.
4. **Build Command**: `pip install -r requirements.txt`
5. **Start Command**: `uvicorn src.main:app --host 0.0.0.0 --port $PORT`

## Connecting to ChatGPT (Apps SDK / MCP)

This server acts as an **MCP Server** that exposes the `lint_flow` tool. The tool returns a Skybridge-compatible widget (`text/html+skybridge`) for rich visualization.

1. Deploy the service to a public URL (e.g., `https://your-app.onrender.com`).
2. Register the app in the OpenAI Developer Portal (for Apps SDK) using the manifest at `/.well-known/ai-plugin.json`.
3. Alternatively, for **Custom Actions (GPTs)**:
   - Import configuration from `https://your-app.onrender.com/openapi.yaml`.
   - Ensure the model knows how to interpret the `ui` field in the response (Skybridge pattern).

## Connecting to Claude (Desktop)

Add the server to your Claude Desktop configuration (`claude_desktop_config.json`):

**Local:**
```json
{
  "mcpServers": {
    "ivr-linter": {
      "command": "uvicorn",
      "args": ["src.main:app", "--port", "8000"],
      "cwd": "/absolute/path/to/ivr-flow-linter"
    }
  }
}
```

**Remote (via Stdio Wrapper - Advanced):**
(Typically Claude Desktop connects to local processes. For remote MCP, use a local bridge or simple local-proxy).

## Examples

See `/examples` directory for 10 sample flows (5 valid, 5 invalid) including:
- `valid_basic.json`: Simple greeting
- `valid_payment.json`: Transaction flow
- `invalid_unreachable.json`: Disconnected nodes
- `invalid_dead_end.json`: Stuck user path