# IVR Flow Linter



**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)

## 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