# Project export: A.R.I.S.E.

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 12.0
- Tagline: AI-driven command layer that monitors real-time flight and cargo data, detects operational risks, and calls ground operators with autonomous voice alerts and recommended actions.
- Devpost: https://devpost.com/software/a-r-i-s-e
- GitHub: https://github.com/M1Z8N/calhacks-2025
- Video: https://www.youtube.com/embed/kQ4phJM9QjM?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 4 GitHub contributor(s) — Claude (13 commits), M1Z8N (12 commits), Hunter Nguyen (4 commits), rnshim (4 commits)

## Devpost submission (written by the team)

### Inspiration

Despite massive automation in aviation, most air-cargo operations still rely on manual triage — people scanning dashboards, making phone calls, and sending emails whenever disruptions occur. During severe weather or ATC congestion, it can take 15–30 minutes for a single reroute or gate reassignment to be approved and executed, costing tens of thousands per delay and jeopardizing SLA-critical freight and perishables. By the time humans piece together the situation and coordinate a response, valuable minutes are lost. Automated Routing & Inventory for Shipping Efficiency (A.R.I.S.E.) changes that by autonomously monitoring airspace, reasoning through alternatives, and orchestrating coordinated responses in real time.

### What it does

A.R.I.S.E. is an autonomous “watchtower” for air cargo operations. It continuously monitors airspace and airport conditions, pulling data from FAA advisories, ADS-B streams, and scraped operational feeds via Bright Data. When it detects a potential disruption (e.g., weather risk, reduced ATC capacity, or runway change), it triggers a Fetch.AI multi-agent reasoning loop to generate a decision plan with reroute options and risk scores. Then, using our agent MCP, A.R.I.S.E. automatically sends messages or calls on-duty handlers through Vapi, presenting a short, human-readable summary (“Flight DL104 facing +60m delay due to IFR — move ULDs 4A–4D to Gate 6?”). The result is a closed-loop, explainable AI assistant that handles disruptions in real time, no dashboards, no emails, just autonomous coordination.

### How we built it

Fetch.AI Agents - reason over multimodal data and produce ranked response plans (reroute, hold, transfer). Bright Data - scrapes FAA ATCSCC advisories, airport capacity reports, and weather data into normalized JSON feeds. Claude API - condenses decision context into a natural-language “speak plan” for voice delivery. Vapi - delivers outbound voice calls to real humans (simulated in demo) and collects DTMF acknowledgments. ChromaDB - stores past incidents and responses for retrieval-augmented learning.

### Challenges we ran into

Multi-agent state coordination — Getting 5 Fetch.ai uAgents to pass structured data sequentially without losing context required building a bureau coordinator that manages workflow execution and validates outputs at each stage. Real-time scraping reliability — Public flight plan data doesn't exist in accessible APIs—airlines and airports don't expose operational details. We used Bright Data to scrape live airport status pages, built custom HTML parsers to normalize tables into JSON, and implemented 5-minute caching with stale-data fallback when scraping fails.

### Accomplishments we're proud of

Built a complete closed-loop system (detection → reasoning → action → acknowledgment) that runs in 2-5 seconds with live data integration (Bright Data scraping SFO flights), true multi-agent coordination (Fetch.AI), and voice interface (Vapi with DTMF). ChromaDB learning makes it smarter over time.

### What we learned

AI agents need structure: free-form communication was chaos. Strict JSON schemas with AS1 LLM made the workflow reliable. Real-time data integration taught us that context matters more than speed; ChromaDB's case-based retrieval improved decisions more than faster inference.

### What's next

Multi-airport cascade analysis, crew/gate resource optimization, and what-if simulation engine

## README (from the GitHub repository)

# A.R.I.S.E

**Automated Routing & Inventory for Shipping Efficiency**

A.R.I.S.E is an AI-powered airline operations control center that autonomously manages flight routing, crew scheduling, and resource inventory while responding to operational disruptions in real-time using a multi-agent system.

## What It Solves

Airlines face constant operational challenges: weather delays, mechanical issues, crew scheduling conflicts, and cascading disruptions. Traditional operations centers rely on manual routing decisions and inventory management, leading to:

- Inefficient flight routing and resource allocation
- Poor inventory visibility across crew, aircraft, and cargo
- Delayed decision-making during critical incidents
- Inconsistent risk assessment and compliance checking
- Reactive rather than proactive operations

A.R.I.S.E solves this by providing an intelligent, autonomous system that:

- **Optimizes routing** for flights and crew assignments in real-time
- **Manages inventory** of aircraft, crew, and operational resources
- **Detects incidents** from multiple data sources automatically
- **Analyzes impact** across flights, schedules, and resource availability
- **Generates action plans** with automated routing adjustments and inventory reallocation
- **Coordinates execution** via automated communications (email, SMS, voice calls)
- **Learns from history** using vector memory to improve decision-making

## Key Features

- **Multi-Agent System**: Specialized AI agents for narration, impact analysis, options generation, risk assessment, and scoring
- **Real-Time Flight Data**: Live flight tracking and status monitoring
- **Interactive Map**: Visualize affected flights, weather patterns, and operational zones
- **Voice Integration**: VAPI-powered voice calls for approvals and notifications
- **Vector Memory**: ChromaDB-based case retrieval for experience-based decision making
- **Automated Actions**: Email, Slack, and calendar integrations via Composio

## Tech Stack

### Frontend
- **Next.js 14** (App Router)
- **React** with TypeScript
- **Tailwind CSS** for styling
- **Mapbox GL** for interactive mapping
- **Zustand** for state management
- **Framer Motion** for animations

### Backend
- **Python 3.11+**
- **FastAPI** for REST API
- **Fetch.ai (ASI:One)** for multi-agent orchestration
- **ChromaDB** for vector memory and case retrieval
- **VAPI** for voice call integration
- **Composio** for email/Slack/calendar automation

### External APIs
- **AviationStack** - Live flight data
- **Bright Data** - Web scraping for airport information
- **Mapbox** - Map visualization

## Getting Started

### Prerequisites

- **Node.js 18+** and npm
- **Python 3.11+** and pip
- **Git**

### 1. Clone the Repository

```bash
git clone https://github.com/yourusername/calhacks-2025.git
cd calhacks-2025
```

### 2. Set Up Environment Variables

Copy the example environment file to create your own:

```bash
cp be/.env.example .env
```

Edit `.env` and fill in your API keys:

**Required Keys:**
- `ASI_ONE_API_KEY` - Get from [Fetch.ai](https://fetch.ai)
- `VAPI_API_KEY` - Get from [VAPI](https://vapi.ai)
- `COMPOSIO_API_KEY` - Get from [Composio](https://composio.dev)
- `CHROMA_API_KEY` - Get from [ChromaDB Cloud](https://www.trychroma.com)
- `NEXT_PUBLIC_MAPBOX_TOKEN` - Get from [Mapbox](https://account.mapbox.com)

**Optional Keys:**
- `AVIATIONSTACK_API_KEY` - For real flight data
- `BRIGHTDATA_API_KEY` - For web scraping

### 3. Install Dependencies

#### Frontend
```bash
cd fe
npm install
cd ..
```

#### Backend
```bash
cd be
pip install -r requirements.txt
cd ..
```

### 4. Seed the Database (Optional)

Populate ChromaDB with historical incident data for case-based reasoning:

```bash
cd be
python3 seed_chromadb.py
cd ..
```

### 5. Start the Application

The easiest way is to use the start script:

```bash
./start.sh
```

Or start services manually:

#### Terminal 1 - Backend
```bash
cd be
python3 -m src.rest_server
```

#### Terminal 2 - Frontend
```bash
cd fe
npm run dev
```

### 6. Access the Application

- **Frontend**: http://localhost:3000
- **Backend API**: http://localhost:8000
- **API Docs**: http://localhost:8000/docs

## Project Structure

```
calhacks-2025/
├── fe/                      # Next.js frontend
│   ├── app/                 # App router pages
│   ├── components/          # React components
│   │   ├── arise/          # A.R.I.S.E specific components
│   │   └── ops-room/       # Operations room components
│   └── lib/                # Utilities and stores
│
├── be/                      # Python backend
│   ├── src/
│   │   ├── agents/         # Multi-agent system
│   │   ├── api/            # FastAPI routes
│   │   ├── core_logic.py   # Core processing logic
│   │   ├── bureau_coordinator.py  # Agent coordination
│   │   └── rest_server.py  # FastAPI server
│   └── seed_chromadb.py    # Database seeding script
│
├── .env                     # Environment variables (create from .env.example)
└── start.sh                # Startup script
```

## Usage

### Triggering an Incident

1. Navigate to http://localhost:3000/trigger
2. Select an incident scenario (weather delay, mechanical issue, etc.)
3. Watch as the multi-agent system:
   - Narrates the incident
   - Analyzes impact on flights and resources
   - Generates action plan options
   - Assesses risks and compliance
   - Scores and selects the best plan
   - Coordinates execution

### Viewing the Operations Room

The main dashboard at http://localhost:3000 shows:
- **Live flight map** with affected aircraft
- **Incident timeline** with agent reasoning
- **Action plan** with execution status
- **KPI metrics** tracking resolution progress

## Voice Integration (Optional)

To enable voice approvals and notifications:

1. Set up a [VAPI](https://vapi.ai) account and create assistants
2. Configure phone numbers in `.env`
3. For local testing, use [ngrok](https://ngrok.com) to expose your backend:
   ```bash
   ngrok http 8000
   ```
4. Update `BACKEND_URL` in `.env` with your ngrok URL

## Development

### Frontend Development
```bash
cd fe
npm run dev
```

### Backend Development
```bash
cd be
python3 -m src.rest_server
```

### Type Checking (Frontend)
```bash
cd fe
npm run type-check
```

### Linting (Frontend)
```bash
cd fe
npm run lint
```

## Security

All API keys and sensitive data are stored in the `.env` file, which is:
- Excluded from Git via `.gitignore`
- Never committed to the repository
- Kept local to your machine

Never commit your `.env` file or share your API keys publicly.

## Contributing

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## License

This project was created for CalHacks 2025.

## Acknowledgments

- Built with [Fetch.ai](https://fetch.ai) multi-agent framework
- Powered by [VAPI](https://vapi.ai) for voice integration
- Integrated with [Composio](https://composio.dev) for automation
- Flight data from [AviationStack](https://aviationstack.com)
- Maps by [Mapbox](https://mapbox.com)

---

Built with passion for CalHacks 2025


## Detected evidence (automated analysis)

Indexed codebase: 77 recognized source files, 487 KB.
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- Next.js (technology) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- AI coding agent: Claude Code — evidence: commit authorship or trailers

## Codebase structure (from repository index)

### Files (86 of 86)

```
.gitignore
be/.env.example
be/.gitignore
be/AGENTS_README.md
be/QUICKSTART.md
be/README.md
be/render.yaml
be/requirements.txt
be/seed_chromadb.py
be/server.py
be/src/agent_messages.py
be/src/agents/__init__.py
be/src/agents/impact_agent_v2.py
be/src/agents/impact_agent.py
be/src/agents/narrator_agent_v2.py
be/src/agents/narrator_agent.py
be/src/agents/options_agent_v2.py
be/src/agents/options_agent.py
be/src/agents/risk_compliance_agent_v2.py
be/src/agents/risk_compliance_agent.py
be/src/agents/scorer_agent_v2.py
be/src/agents/scorer_agent.py
be/src/as1_client.py
be/src/bureau_coordinator.py
be/src/core_logic.py
be/src/memory_service.py
be/src/orchestrator.py
be/src/rest_server.py
be/src/server_v2.py
be/src/server.py
fe/.gitignore
fe/app/api/ack-from-voice/route.ts
fe/app/api/agents/process-incident/route.ts
fe/app/api/agents/status/route.ts
fe/app/api/agents/store-resolution/route.ts
fe/app/api/flights/live/route.ts
fe/app/api/flights/sfo-live/route.ts
fe/app/api/route.ts
fe/app/api/vapi-call/route.ts
fe/app/globals.css
fe/app/layout.tsx
fe/app/page.tsx
fe/app/trigger/page.tsx
fe/components/arise/action-log.tsx
fe/components/arise/animated-reasoning.tsx
fe/components/arise/control-panel.tsx
fe/components/arise/event-timeline.tsx
fe/components/arise/kpi-bar-enhanced.tsx
fe/components/arise/plan-selector.tsx
fe/components/arise/reasoning-panel.tsx
fe/components/arise/schedule-board.tsx
fe/components/ops-room/action-timeline.tsx
fe/components/ops-room/active-incident.tsx
fe/components/ops-room/agent-coordination.tsx
fe/components/ops-room/evidence-pack.tsx
fe/components/ops-room/incident-card.tsx
fe/components/ops-room/incident-feed.tsx
fe/components/ops-room/kpi-bar.tsx
fe/components/ops-room/unified-map.tsx
fe/components/ops-room/what-if-slider.tsx
fe/components/ui/badge.tsx
fe/components/ui/button.tsx
fe/components/ui/card.tsx
fe/components/ui/checkbox.tsx
fe/components/ui/label.tsx
fe/components/ui/select.tsx
fe/components/ui/slider.tsx
fe/components/ui/tabs.tsx
fe/components/ui/textarea.tsx
fe/components/ui/tooltip.tsx
fe/lib/arise-fixtures.ts
fe/lib/arise-simulator.ts
fe/lib/arise-store.ts
fe/lib/arise-types.ts
fe/lib/mock-data.ts
fe/lib/utils.ts
fe/lib/vapi.ts
fe/next.config.mjs
fe/package.json
fe/postcss.config.mjs
fe/README.md
fe/tailwind.config.ts
fe/tsconfig.json
fe/VAPI_USAGE.md
README.md
start.sh
```

### Dependencies

- be/requirements.txt: aiohttp@>=3.9.0, chromadb@>=0.4.0, fastapi@>=0.115.0, fastmcp@>=2.12.0, openai@>=1.0.0, pydantic@>=2.0.0, requests@>=2.31.0, uagents@>=0.12.0, uvicorn@>=0.35.0
- fe/package.json: @chroma-core/default-embed@^0.1.8, @radix-ui/react-checkbox@^1.3.3, @radix-ui/react-label@^2.1.7, @radix-ui/react-select@^2.2.6, @radix-ui/react-slider@^1.3.6, @radix-ui/react-tooltip@^1.2.8, @types/node@^24.9.1, @types/react@^19.2.2, @vapi-ai/web@^2.5.0, autoprefixer@^10.4.21, chromadb@^3.0.17, class-variance-authority@^0.7.1, clsx@^2.1.1, framer-motion@^12.23.24, lucide-react@^0.548.0, mapbox-gl@^3.16.0, next@^16.0.0, openai@^6.7.0, postcss@^8.5.6, react@^19.2.0, react-dom@^19.2.0, react-map-gl@^8.1.0, recharts@^3.3.0, tailwind-merge@^3.3.1, tailwindcss@^3.4.18, typescript@^5.9.3, zod@^4.1.12, zustand@^5.0.8

### Recent commits (newest first)

- Add incident trigger and status tracking API endpoints
- Fix backend startup by removing non-existent API module imports
- Fix A.R.I.S.E acronym and enhance description
- Enhance multi-agent system and improve operational interface
- Consolidate environment configuration and add comprehensive documentation
- Enhance multi-agent system with deeper reasoning and analysis
- Merge pull request #2 from M1Z8N/rename-watchtower-to-arise
- Rename project from Watchtower to A.R.I.S.E
- add fetch changes
- Enhance Watchtower with live flight data, multi-agent system, and improved UX
- Merge pull request #1 from M1Z8N/vapi
- add vapi
- Add ChromaDB integration with API route and embedding support
- Enhance Watchtower with advanced flight mapping and UI improvements
- Add comprehensive Watchtower features to unified dashboard
- added outline doc
- doc
- add backend
- Improve UI layout and readability
- Initial commit: flight operations and incident management system

## Key source files (fetched from GitHub, selected and truncated for size)

### fe/VAPI_USAGE.md

```markdown
# Vapi Voice Call Integration

This project includes a complete Vapi integration for making voice calls with context-aware messaging and acknowledgment tracking.

## API Endpoints

### 1. Initiate Voice Call

**Endpoint:** `POST /api/vapi-call`

**Request Body:**
```json
{
  "customerNumber": "+1234567890",
  "context": {
    "incidentType": "Medical Emergency",
    "flight": "AA123",
    "risk": "High",
    "recommendedOption": "Divert to nearest airport",
    "nextAction": "Prepare for emergency landing",
    "whoToCall": "Ground Control Tower",
    "requestedAckFormat": "pressing 1"
  },
  "callbackUrl": "https://yourdomain.com/api/ack-from-voice"
}
```

**Response:**
```json
{
  "success": true,
  "message": "Voice call initiated successfully",
  "data": {
    "callId": "call_abc123",
    "status": "initiated",
    "speakPlan": "Incident type: Medical Emergency. Flight: AA123...",
    "voiceScript": "<speak>...</speak>"
  }
}
```

### 2. Acknowledgment Callback

**Endpoint:** `POST /api/ack-from-voice`

This endpoint receives callbacks from Vapi when the call recipient responds.

**Webhook Payload from Vapi:**
```json
{
  "callId": "call_abc123",
  "status": "completed",
  "dtmfInput": "1",
  "timestamp": "2025-01-25T10:30:00Z"
}
```

**Response Types:**
- DTMF "1" → "acknowledged"
- DTMF "2" → "more_info"
- DTMF "3" → "escalate"
- Speech input is also parsed for keywords

## Usage Example

### From Client-Side (React Component)

```typescript
async function initiateEmergencyCall() {
  const response = await fetch('/api/vapi-call', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      customerNumber: '+1234567890',
      context: {
        incidentType: 'Medical Emergency',
        flight: 'AA123',
        risk: 'High',
        recommendedOption: 'Divert to nearest airport',
        nextAction: 'Prepare for emergency landing',
        whoToCall: 'Ground Control Tower',
        requestedAckFormat: 'pressing 1',
      },
    }),
  });

  const result = await response.json();
  console.log('Call initiated:', result);
}
```

### From Server-Side (API Route or Server Action)

```typescript
import { vapiService } from '@/lib/vapi';

const result = await vapiService.makeContextualCall(
  {
    incidentType: 'Medical Emergency',
    flight: 'AA123',
    risk: 'High',
    recommendedOption: 'Divert to nearest airport',
    nextAction: 'Prepare for emergency landing',
    whoToCall: 'Ground Control Tower',
    requestedAckFormat: 'pressing 1',
  },
  '+1234567890'
);

console.log('Call:', result.call);
console.log('Script:', result.voiceScript);
```

## Architecture

1. **VapiService** (`lib/vapi.ts`):
   - Initializes Vapi client with environment variables
   - `composeSpeakPlan()`: Creates structured message from context
   - `renderVoiceScript()`: Converts plan to SSML voice script
   - `makeCall()`: Executes the Vapi call
   - `makeContextualCall()`: Complete workflow for context-awar
[truncated — 941 more characters]
```

### be/QUICKSTART.md

```markdown
# A.R.I.S.E Multi-Agent System - Quick Start

## What I Built

A complete **5-agent autonomous decision-making system** powered by:
- **fetch.ai uAgents** - Multi-agent coordination
- **AgentStation AS1 LLM** - Reasoning engine
- **ChromaDB** - Vector memory for case-based learning
- **FastMCP** - API server for frontend integration

## File Structure

```
be/
├── src/
│   ├── server.py                    # FastMCP server (main entry point)
│   ├── orchestrator.py              # Coordinates all 5 agents
│   ├── as1_client.py                # AS1 LLM client wrapper
│   ├── memory_service.py            # ChromaDB vector memory
│   └── agents/
│       ├── __init__.py              # Package exports
│       ├── impact_agent.py          # Analyzes severity & impact
│       ├── options_agent.py         # Generates recovery plans A/B/C
│       ├── risk_compliance_agent.py # Validates constraints
│       ├── scorer_agent.py          # Ranks options
│       └── narrator_agent.py        # Explains decisions
├── test_agents.py                   # Test script
├── requirements.txt                 # Python dependencies
├── .env.example                     # Environment template
├── AGENTS_README.md                 # Full documentation
└── QUICKSTART.md                    # This file
```

## Installation (60 seconds)

```bash
# 1. Navigate to backend
cd /Users/mizan/calhacks-2025/be

# 2. Install dependencies
pip install -r requirements.txt

# 3. Set up environment
cp .env.example .env

# 4. Add your AS1 API key
echo "AS1_API_KEY=your-key-here" >> .env
# OR edit .env manually
```

## Running the System

### Option 1: Start the Server

```bash
cd src
python server.py
```

You should see:
```
============================================================
🛩️  A.R.I.S.E
============================================================
Server starting on 0.0.0.0:8000

🤖 Multi-Agent System:
   1. Impact Agent - Analyzes severity
   2. Options Agent - Generates recovery plans
   3. Risk/Compliance Agent - Validates constraints
   4. Scorer Agent - Ranks options
   5. Narrator Agent - Explains decisions

💾 Services:
   - AS1 LLM: ✅ Configured
   - ChromaDB: ✅ Active
============================================================
```

### Option 2: Run Test Script

```bash
python test_agents.py
```

This will:
1. Initialize all 5 agents
2. Process a sample weather incident (LAX thunderstorms)
3. Show complete decision pipeline results
4. Take ~2-5 seconds to complete

## How It Works

### The Pipeline

```
Incident → Impact → Options → Risk → Scorer → Narrator → Decision
           Agent     Agent      Agent   Agent    Agent
```

1. **Impact Agent**: "This is a HIGH severity incident affecting 3 ULDs"
2. **Options Agent**: "Here are 3 recovery plans: A (fast/expensive), B (balanced), C (slow/cheap)"
3. **Risk Agent**: "Option A passes all constraints, Option B has CUSTOMS warning, Option C fails CREW check"
4. **Scorer Agent**: "Option A ranks #1 with 8.5/10 score, 85% confiden
[truncated — 6883 more characters]
```

### be/requirements.txt

```
fastmcp>=2.12.0
uvicorn>=0.35.0
fastapi>=0.115.0
requests>=2.31.0

# fetch.ai uAgents framework
uagents>=0.12.0

# LLM and AI
openai>=1.0.0

# Vector database for memory
chromadb>=0.4.0

# Data processing
pydantic>=2.0.0

# Async support
aiohttp>=3.9.0

```

### fe/package.json

```
{
  "name": "fe",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@chroma-core/default-embed": "^0.1.8",
    "@radix-ui/react-checkbox": "^1.3.3",
    "@radix-ui/react-label": "^2.1.7",
    "@radix-ui/react-select": "^2.2.6",
    "@radix-ui/react-slider": "^1.3.6",
    "@radix-ui/react-tooltip": "^1.2.8",
    "@vapi-ai/web": "^2.5.0",
    "chromadb": "^3.0.17",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "framer-motion": "^12.23.24",
    "lucide-react": "^0.548.0",
    "mapbox-gl": "^3.16.0",
    "next": "^16.0.0",
    "openai": "^6.7.0",
    "react": "^19.2.0",
    "react-dom": "^19.2.0",
    "react-map-gl": "^8.1.0",
    "recharts": "^3.3.0",
    "tailwind-merge": "^3.3.1",
    "zod": "^4.1.12",
    "zustand": "^5.0.8"
  },
  "devDependencies": {
    "@types/node": "^24.9.1",
    "@types/react": "^19.2.2",
    "autoprefixer": "^10.4.21",
    "postcss": "^8.5.6",
    "tailwindcss": "^3.4.18",
    "typescript": "^5.9.3"
  }
}

```

### be/server.py

```python
#!/usr/bin/env python3
import os
import requests
from fastmcp import FastMCP

mcp = FastMCP("Sample MCP Server")

@mcp.tool(description="Greet a user by name with a welcome message from the MCP server")
def greet(name: str) -> str:
    return f"Hello, {name}! Welcome to our sample MCP server running on Heroku!"

@mcp.tool(description="Get information about the MCP server including name, version, environment, and Python version")
def get_server_info() -> dict:
    return {
        "server_name": "Sample MCP Server",
        "version": "1.0.0",
        "environment": os.environ.get("ENVIRONMENT", "development"),
        "python_version": os.sys.version.split()[0]
    }

if __name__ == "__main__":
    port = int(os.environ.get("PORT", 8000))
    host = "0.0.0.0"
    
    print(f"Starting FastMCP server on {host}:{port}")
    
    mcp.run(
        transport="http",
        host=host,
        port=port,
        stateless_http=True
    )

```

### fe/app/layout.tsx

```typescript
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "A.R.I.S.E.",
  description: "Autopilot for ground delays",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en" className="dark">
      <body className={inter.className}>{children}</body>
    </html>
  );
}

```

### fe/app/page.tsx

```typescript
"use client";

import { KPIBarEnhanced } from "@/components/arise/kpi-bar-enhanced";
import { ControlPanel } from "@/components/arise/control-panel";
import { ScheduleBoard } from "@/components/arise/schedule-board";
import { ReasoningPanel } from "@/components/arise/reasoning-panel";
import { ActionLog } from "@/components/arise/action-log";
import { EventTimeline } from "@/components/arise/event-timeline";
import { UnifiedMap } from "@/components/ops-room/unified-map";
import { PlanSelector } from "@/components/arise/plan-selector";

export default function CommandCenter() {

  return (
    <div className="h-screen flex flex-col bg-background">
      {/* Top: KPI Bar */}
      <KPIBarEnhanced />

      {/* Control Panel */}
      <ControlPanel />

      {/* Main Dashboard */}
      <div className="flex-1 overflow-hidden p-4">
        <div className="h-full grid grid-cols-12 gap-4">
          {/* Left Column: Schedule Board + Event Timeline */}
          <div className="col-span-3 flex flex-col gap-4 overflow-hidden">
            {/* Schedule Board */}
            <div className="h-[60%] bg-card rounded-lg border overflow-hidden flex-shrink-0">
              <ScheduleBoard />
            </div>

            {/* Event Timeline */}
            <div className="flex-1 bg-card rounded-lg border overflow-hidden min-h-0">
              <EventTimeline />
            </div>
          </div>

          {/* Center Column (Expanded): Plan Selector + Map */}
          <div className="col-span-9 overflow-hidden flex flex-col gap-2">
            {/* Plan Selector - PROMINENT comparison buttons */}
            <PlanSelector />

            {/* Map */}
            <div className="flex-1 bg-card rounded-lg border overflow-hidden">
              <UnifiedMap />
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

```

### be/src/server.py

```python
#!/usr/bin/env python3
import os
import asyncio
from typing import Dict, Any, List
from fastmcp import FastMCP
from orchestrator import AgentOrchestrator

# Initialize FastMCP server
mcp = FastMCP("A.R.I.S.E")

# Global orchestrator instance (initialized on startup)
orchestrator: AgentOrchestrator = None


def get_orchestrator() -> AgentOrchestrator:
    """Get or create orchestrator instance"""
    global orchestrator
    if orchestrator is None:
        orchestrator = AgentOrchestrator(
            as1_api_key=os.environ.get("ASI_ONE_API_KEY"),
            as1_base_url=os.environ.get("ASI_ONE_BASE_URL"),
            chroma_persist_dir=os.environ.get("CHROMA_PERSIST_DIR", "./chroma_data")
        )
    return orchestrator


@mcp.tool(description="Process an aviation incident through multi-agent decision-making workflow")
async def process_incident(
    incident_id: str,
    incident_type: str,
    description: str,
    flight_id: str,
    departure: str,
    arrival: str,
    scheduled_time: str,
    affected_ulds: List[Dict[str, Any]],
    current_location: str,
    policy_guardrails: Dict[str, Any] = None
) -> dict:
    """
    Process incident through 5-agent workflow

    Args:
        incident_id: Unique incident ID
        incident_type: WEATHER, ATC, MECHANICAL, CUSTOMS, or ROUTING
        description: Human-readable description
        flight_id: Flight identifier
        departure: Departure airport code
        arrival: Arrival airport code
        scheduled_time: Scheduled departure time (ISO format)
        affected_ulds: List of affected cargo containers
        current_location: Current flight location
        policy_guardrails: Optional policy constraints

    Returns:
        Complete decision package with recommendations
    """
    orch = get_orchestrator()

    incident_data = {
        "incident_id": incident_id,
        "incident_type": incident_type,
        "description": description,
        "flight_id": flight_id,
        "departure": departure,
        "arrival": arrival,
        "scheduled_time": scheduled_time,
        "affected_ulds": affected_ulds,
        "current_location": current_location
    }

    result = await orch.process_incident(incident_data, policy_guardrails)
    return result


@mcp.tool(description="Store a resolved incident outcome in memory for case-based learning")
async def store_resolution(
    incident_id: str,
    incident_type: str,
    description: str,
    severity: str,
    affected_ulds: List[str],
    resolution: Dict[str, Any],
    outcome: Dict[str, Any]
) -> dict:
    """
    Store resolved incident for future reference

    Args:
        incident_id: Incident ID
        incident_type: Type
        description: Description
        severity: CRITICAL, HIGH, MEDIUM, or LOW
        affected_ulds: List of ULD IDs
        resolution: Executed action plan
        outcome: Final outcome metrics

    Returns:
        Confirmation message
    """
    orch = get_orchestrator()

    await orch.store_resolution(
        incident_id=incident_id,
        incident_type=incident_type,
        description=description,
        severity=severity,
        affected_ulds=affected_ulds,
        resolution=resolution,
        outcome=outcome
    )

    return {"status": "success", "incident_id": incident_id, "stored": True}


@mcp.tool(description="Get memory service statistics including total stored incidents")
def get_memory_stats() -> dict:
    """
    Get memory statistics

    Returns:
        Memory stats
    """
    orch = get_orchestrator()
    return orch.get_memory_stats()


@mcp.tool(description="Get server information and agent status")
def get_server_info() -> dict:
    """Get server and agent information"""
    return {
        "server_name": "A.R.I.S.E",
        "version": "2.0.0",
        "environment": os.environ.get("ENVIRONMENT", "development"),
        "python_version": os.sys.version.split()[0],
        "agents": {
            "impact_agent": "Active",
            "options_agent": "Active",
            "risk_compliance_agent": "Active",
            "scorer_agent": "Active",
            "narrator_agent": "Active"
        },
        "services": {
            "llm": "Configured" if os.environ.get("ASI_ONE_API_KEY") else "Not configured",
            "chromadb": "Active"
        }
    }


if __name__ == "__main__":
    port = int(os.environ.get("PORT", 8000))
    host = "0.0.0.0"

    print("=" * 60)
    print("🛩️  A.R.I.S.E")
    print("=" * 60)
    print(f"Server starting on {host}:{port}")
    print("\n🤖 Multi-Agent System:")
    print("   1. Impact Agent - Analyzes severity")
    print("   2. Options Agent - Generates recovery plans")
    print("   3. Risk/Compliance Agent - Validates constraints")
    print("   4. Scorer Agent - Ranks options")
    print("   5. Narrator Agent - Explains decisions")
    print("\n💾 Services:")
    llm_configured = os.environ.get('ASI_ONE_API_KEY')
    print(f"   - LLM (ASI:One): {'✅ Configured' if llm_configured else '❌ Not configured'}")
    print("   - ChromaDB: ✅ Active")
    print("=" * 60)

    mcp.run(
        transport="http",
        host=host,
        port=port,
        stateless_http=True
    )

```

### fe/app/api/route.ts

```typescript
import { NextRequest, NextResponse } from "next/server";
import { CloudClient, Collection, Metadata } from "chromadb";
import { DefaultEmbeddingFunction } from "@chroma-core/default-embed";

interface AddDataRequest {
  ids: string[];
  documents: string[];
  metadatas: Metadata[];
}

const chromaClient = new CloudClient({
  apiKey: process.env.CHROMA_API_KEY,
  tenant: process.env.CHROMA_TENANT,
  database: process.env.CHROMA_DATABASE,
});

const embedder = new DefaultEmbeddingFunction();

let myCollection: Collection | null = null;

const getMyCollection = async () => {
  if (!myCollection) {
    myCollection = await chromaClient.getOrCreateCollection({
      name: "myCollection",
      embeddingFunction: embedder,
    });
  }
  return myCollection;
};

export async function POST(request: NextRequest) {
  try {
    const data: AddDataRequest = await request.json();
    const collection = await getMyCollection();

    await collection.add({
      ids: data.ids,
      documents: data.documents,
      metadatas: data.metadatas,
    });

    return NextResponse.json({
      success: true,
      message: "Data added successfully",
      data,
    });
  } catch (error) {
    console.error(error);
    return NextResponse.json(
      { success: false, message: "Failed to add data" },
      { status: 500 },
    );
  }
}


```

### fe/app/trigger/page.tsx

```typescript
"use client";

import { useState } from "react";
import { useRouter } from "next/navigation";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Zap, Check, Plane, Loader2, Phone, Mail, Calendar } from "lucide-react";
import { motion, AnimatePresence } from "framer-motion";
import { useAriseStore } from "@/lib/arise-store";
import { Incident } from "@/lib/arise-types";
import { useIncidentStatus } from "@/lib/hooks/useIncidentStatus";

export default function TriggerPage() {
  const [isTriggered, setIsTriggered] = useState(false);
  const [isProcessing, setIsProcessing] = useState(false);
  const [selectedFlight, setSelectedFlight] = useState<string | null>(null);
  const [incidentId, setIncidentId] = useState<string | null>(null);
  const router = useRouter();
  const processIncidentWithAgents = useAriseStore(state => state.processIncidentWithAgents);
  const { status } = useIncidentStatus(incidentId);

  const mockFlights = [
    { flight: "FDX412", dep: "LAX", arr: "NRT", delay: 240, reason: "WEATHER", description: "Severe thunderstorms at LAX" },
    { flight: "FDX503", dep: "SFO", arr: "ORD", delay: 120, reason: "ATC", description: "ATC delays at SFO" },
    { flight: "FDX822", dep: "MEM", arr: "LAX", delay: 90, reason: "MECHANICAL", description: "Mechanical issue detected" },
  ];

  const handleTrigger = async (flight: typeof mockFlights[0]) => {
    setSelectedFlight(flight.flight);
    setIsProcessing(true);

    try {
      // Call the NEW incident flow API!
      const response = await fetch('http://localhost:8888/api/incident/trigger', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          description: flight.description,
          severity: flight.reason === 'WEATHER' ? 'HIGH' : 'MEDIUM',
          flight_data: {
            flight_id: flight.flight,
            departure: flight.dep,
            arrival: flight.arr,
            scheduled_time: new Date().toISOString(),
          },
          location: flight.dep,
        }),
      });

      if (!response.ok) {
        throw new Error('Failed to trigger incident');
      }

      const data = await response.json();
      setIncidentId(data.incident_id);
      setIsTriggered(true);

    } catch (error) {
      console.error("Error triggering incident:", error);
      setIsProcessing(false);
    }
  };

  return (
    <div className="min-h-screen bg-gradient-to-br from-background via-background to-primary/5 flex items-center justify-center p-6">
      <Card className="w-full max-w-2xl">
        <CardHeader className="text-center">
          <div className="flex justify-center mb-4">
            <div className="p-4 rounded-full bg-primary/10">
              <Zap className="h-12 w-12 text-primary" />
            </div>
          </div>
          <CardTitle className="text-3xl">A.R.I.S.E.</CardTitle>
          <CardDescription className="text-lg">
            Trigger a ground delay incident
          </CardDescription>
        </CardHeader>

        <CardContent className="space-y-6">
          <AnimatePresence mode="wait">
            {isProcessing ? (
              <motion.div
                key="processing"
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                className="text-center space-y-6 py-12"
              >
                <div className="flex justify-center">
                  <Loader2 className="h-16 w-16 text-primary animate-spin" />
                </div>
                <div>
                  <h3 className="text-xl font-bold">Processing with Agents...</h3>
                  <p className="text-sm text-muted-foreground mt-2">
                    5 AI agents are analyzing the incident and generating recovery plans
                  </p>
                </div>
              </motion.div>
            ) : !isTriggered ? (
              <motion.div
                key="select"
                initial={{ opacity: 0, y: 20 }}
                animate={{ opacity: 1, y: 0 }}
                exit={{ opacity: 0, y: -20 }}
                className="space-y-4"
              >
                <p className="text-sm text-muted-foreground text-center">
                  Select a flight to simulate an incident:
                </p>

                <div className="grid gap-3">
                  {mockFlights.map((flight) => (
                    <button
                      key={flight.flight}
                      onClick={() => handleTrigger(flight)}
                      className="p-4 rounded-lg border-2 border-border hover:border-primary bg-card hover:bg-card/80 transition-all text-left group"
                    >
                      <div className="flex items-center justify-between">
                        <div className="flex items-center gap-3">
                          <Plane className="h-5 w-5 text-muted-foreground group-hover:text-primary" />
                          <div>
                            <div className="font-bold text-lg">{flight.flight}</div>
                            <div className="text-sm text-muted-foreground">
                              {flight.dep} → {flight.arr}
                            </div>
                          </div>
                        </div>
                        <div className="text-right">
                          <Badge variant="destructive">+{flight.delay}m</Badge>
                          <div className="text-xs text-muted-foreground mt-1">
                            {flight.reason}
                          </div>
                        </div>
                      </div>
                    </button>
                  ))}
                </div>
              </motion.div>
            ) : status && (
              <motion.div
                key="success"
                initial={
[truncated — 5623 more characters]
```

[66 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]