# Project export: Auto Nexus

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: UC Berkeley AI Hackathon 2025
- Tagline: We have developed a comprehensive business proposal generator. Our solution is designed to provide users with the key tools and support required to successfully run and grow their business.
- Devpost: https://devpost.com/software/auto-nexus
- GitHub: https://github.com/adityarao97/autonexus
- Video: https://www.youtube.com/embed/deDlnYjkVpE?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 2 GitHub contributor(s) — Rajath Nattoji Rajaram (18 commits), Aditya (17 commits)

## Devpost submission (written by the team)

### Inspiration

In today’s fast-paced business world, turning an idea into a viable venture involves navigating complex decisions sourcing materials, evaluating global markets, understanding regulations, and aligning with strategic goals like profitability or sustainability. Most entrepreneurs struggle not due to a lack of vision, but because of fragmented, unstructured planning tools that don’t adapt to their priorities. Our inspiration stems from solving this gap: What if we could empower anyone to build a robust, tailored business plan using intelligent agents and real-time data, all through a simple input? By combining open-source LLMs, autonomous decision agents, agentic workflows and an interactive knowledge graph, we aim to make structured, data-backed business planning accessible, explainable, and adaptive—for everyone from solopreneurs to global operators.

### What it does

Our platform takes a simple business idea and transforms it into a fully structured, data-driven, and interactive business plan. Users provide two inputs: Product context - the product that the user wises to produce. Business Priorities – Key focus areas like profitability, eco-friendliness, or scalability. Location – Target location for setting up the business. Once submitted, here’s what happens: Input is stored via API into a MySQL database. A central MCP server connects to an open-source LLM to interpret the input and build a curated business strategy. The LLM: Identifies required raw materials. Plans import and assembly sequences. Spawns a hierarchical agent system for each material, simulating expert consultants for countries, costs, logistics, and feasibility. Leverages web tools (e.g., Twilio, DuckDuckGo) and specific data sources (e.g., PDFs, CSVs, Kaggle) to inform each agent’s decisions. Each agent collaborates in a tree structure: Autonomous agents analyze costs, risks, and logistics at micro and macro levels. Aggregator agents compare options across countries and optimize for the user’s initial priorities. The best option is selected, but alternatives and justifications are preserved for transparency. The entire process is stored in a Neo4j graph database, allowing: Interactive UI visualization of decision trees. Node-level inspection showing cost, reasoning, and next-best options. Dynamic plan recomputation when users change key decisions. Ultimately, the user receives: A detailed, visualized business plan.

### How we built it

We built a modular, AI-driven architecture that transforms user inputs into a fully structured business plan through a layered pipeline of intelligent agents, decision trees, and visual representation. Frontend & API Layer We created a simple UI that collects two types of user input: business priorities and venture descriptions. Inputs are sent via FAST API and stored in a MongoDB database for persistence and validation. MCP Server & Agent Framework The core of the system is an MCP (Multi-Agent Control Protocol) server, designed to manage and orchestrate AI agents. The server invokes an open-source LLM (via Claude Sonnet 4) to interpret the business idea and break it down into actionable components like raw materials and import needs. Based on these components, the LLM spawns autonomous agents in a hierarchical tree structure. Agent Behavior & Coordination Top-level aggregator agents assign countries for sourcing each raw material. For each country, expert consultant agents are created to evaluate cost, taxes, logistics, and geopolitical factors. These agents use external tools (e.g., DuckDuckGo for search) and custom pipelines to pull data from PDFs, CSVs, APIs, and Kaggle datasets. Data Flow & Decision Encoding Each agent returns a structured JSON output, adhering to a common schema. Intermediate agent outputs are first stored in MongoDB to facilitate quick access and iterative updates. Once finalized, all outputs are transferred into Neo4j, forming a graph-based decision tree. Visualization Layer The UI visualizes the agent decision tree using interactive graph components. Users can hover over nodes to view decisions, rationales, and alternatives and even change decisions, triggering re-evaluation and updating the full business plan dynamically. Reactivity & Scoring System Every agent decision is scored based on the user’s original business priorities (e.g., profitability vs sustainability). A change in one node propagates updates downstream—ensuring the entire business plan stays consistent with user goals.

### Challenges we ran into

Agent Orchestration in MCP Server One of the core challenges was integrating multiple autonomous AI agents within the MCP server and orchestrating their execution flow. Each agent had distinct responsibilities, yet their outputs were interdependent requiring us to design a scalable, modular framework for task delegation and result aggregation. Managing Inter-Agent Dependencies Creating a hierarchy where parent agents could dynamically spawn children, track their outputs, and make informed decisions based on them proved complex. We had to ensure that downstream agents could operate asynchronously yet in coordination with upstream logic. Standardizing JSON Output for Aggregation Each agent’s output had to be structured in a standardized JSON schema to be aggregated and passed up the chain. Designing a universal response schema that could accommodate various decision types and data sources was critical to prevent data loss or misinterpretation. Preprocessing and Structuring Data for Agent Use Before agents could begin their tasks, we needed a robust data processing layer to ingest and clean raw data from PDFs, CSVs, APIs, and scraped web content. Ensuring data quality, relevance, and formatting consistency was a time-consuming but essential step. Transition from MongoDB to Graph-Based Storage Initially, we stored intermediate and final agent outputs in MongoDB for flexibility. However, representing the hierarchical relationships and agent decision flow required us to later transition to a graph database (like Neo4j) to enable real-time visualizations and node-level interactions in the UI.

### Accomplishments we're proud of

Built a Fully Functional Multi-Agent Framework We successfully implemented a dynamic multi-agent system where each agent operates autonomously, collaborates contextually, and makes decisions based on real-world data—structured through a clear parent-child hierarchy. Seamless Integration with Open-Source LLM and Tools Our architecture integrates with open-source LLMs using LangChain and custom tools, enabling agents to fetch and process external data from APIs, search engines, PDFs, and CSVs with minimal latency. Real-Time, Graph-Based Decision Visualization We designed an interactive UI powered by Neo4j that lets users explore each decision point in a visually intuitive tree. Users can see the reasoning behind each choice, compare with alternatives, and dynamically switch paths to regenerate the business plan. Prioritization-Driven Decision Making By tying every decision back to user-defined priorities like profitability or sustainability, we enabled context-aware optimization throughout the entire planning process. Automated Data Ingestion and Processing Pipeline We built a preprocessing layer capable of converting semi-structured inputs from diverse sources (e.g., Kaggle, PDF reports) into usable, agent-readable formats ensuring the system is data-rich and scalable. Dynamic Recalculation on User Interaction One of the most powerful features is our ability to recalculate downstream decisions in real time when a user overrides any node bringing true interactivity and explainability to automated planning.

### What we learned

Agent Collaboration is Not Trivial Getting AI agents to communicate effectively especially when their decisions depend on each other taught us a lot about dependency management, asynchronous task flows, and result aggregation in multi-agent systems. LLMs Need Strong Context Anchoring Without clear system prompts and structured input formatting, open-source LLMs tend to drift. Defining guardrails and limiting their scope helped improve accuracy and task relevance. Graph Databases Unlock Powerful Visualizations Using Neo4j allowed us to not only store relationships meaningfully but also deliver intuitive, node-based interactions in the frontend that would have been complex with relational databases.

### What's next

Agent Memory and Iterative Reasoning We plan to implement long-term memory for agents so they can retain context across decisions, learn from previous interactions, and iterate on strategies without starting from scratch each time. Mobile & Voice Interface Support We want to make Auto Nexus more accessible by launching a mobile-friendly version and integrating with voice assistants, allowing entrepreneurs to build businesses on-the-go.

## README (from the GitHub repository)

# AutoNexus – Multi-Agent Supply Chain Optimization Platform

**AutoNexus** is a multi-agent supply chain optimization platform that uses **Claude MCP agents**, **Python**, **Neo4j**, **MySQL**, and a modern **React** dashboard to intelligently generate, evaluate, and visualize end-to-end logistics plans.

This system supports optimization based on **cost**, **eco-impact**, and **stability**, enabling organizations to explore and compare multiple supply chain strategies with transparent, explainable reasoning.

---

# Clean Setup Instructions

## Pre-requirements
- Install and run **Docker Desktop** (Windows/macOS) or **Docker daemon** (Linux).
- Install **Python 3.8+** with `venv` support.
- Install **Node.js + npm** (LTS recommended).

---

## Steps Done by `run.sh`

1. **Starts Ollama**:
   - Runs Ollama on port `11434`.
   - Pulls the model `gemma3:1b`.

2. **Starts MongoDB**:
   - Builds MongoDB using `./external-services/Dockerfile`.
   - Runs MongoDB on port `27017`.

3. **Sets up Python environment**:
   - Creates a virtual environment `aditya_env` if not already present.
   - Activates it and installs `backend/requirements.txt`.

4. **Runs Backend**:
   - Launches FastAPI backend via `uvicorn app.main:app --reload` from `backend/`.

5. **Runs Frontend**:
   - Installs dependencies (`npm install`) and runs dev server (`npm run dev`) from `frontend/`.

---

## Usage

Make the script executable and run:

```bash
chmod +x run.sh
./run.sh
```

## Tech Stack

### Backend
- Python 3.x  
- Claude MCP Agents  
- FastAPI or Flask  
- Neo4j  
- MySQL  

### Frontend
- React.js  
- Material UI  
- Chart.js / D3.js  

### Dev Tools
- Docker  
- Neo4j Browser  
- Postman / Thunder Client  

---

## 4. Installation

### Clone the repository
```bash
git clone https://github.com/adityarao97/autonexus.git
cd autonexus
```

## Core Components

### Multi-Agent Engine
Dedicated Claude MCP agents for:
- Route generation  
- Cost modeling  
- Emissions scoring  
- Stability/risk assessment  
- Plan synthesis  

### Graph Model (Neo4j)
Represents:
- Suppliers  
- Distribution hubs  
- Warehouses  
- Transport routes  
- Capacities, delays, reliability scores  

### Optimization Pipeline
1. User sets cost/eco/stability weights.  
2. Agents produce candidate plans.  
3. Backend scores and ranks them.  
4. UI visualizes the chosen plan and alternatives.  

### Interactive Dashboard
- Route visualization  
- Cost and emission breakdowns  
- Risk metrics  
- Decision-tree comparisons  

---

## Sample Workflow

1. User inputs or imports supply chain nodes and routes.  
2. Backend updates the Neo4j graph.  
3. Agents generate and evaluate multiple route strategies.  
4. Backend selects optimal plans based on user-defined priorities.  
5. UI displays results, reasoning, and trade-offs.  
6. User iterates and runs simulations.  

---

## Future Enhancements

- Reinforcement learning for autonomous supply chain optimization  
- Real-time disruption monitoring and rerouting  
- Integration with logistics APIs (UPS, FedEx, Maersk, etc.)  
- Multi-agent negotiation for procurement strategies  
- Predictive cost forecasting using ML models  

---

## License

This project currently has no license.  
Add MIT, Apache 2.0, or GPL depending on distribution needs.

---


## Detected evidence (automated analysis)

Indexed codebase: 53 recognized source files, 367 KB.
- Anthropic (technology) — detected in the code
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- Next.js (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- SQL (language) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- MongoDB (technology) — claimed on Devpost, not found in the code
- Vercel (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (60 of 60)

```
.gitignore
backend/app/agents/__init__.py
backend/app/agents/base_agent.py
backend/app/agents/country_agent.py
backend/app/agents/expert_agent.py
backend/app/agents/leader_agent.py
backend/app/agents/material_analyst_agent.py
backend/app/api/__init__.py
backend/app/api/routes.py
backend/app/db/mongodb.py
backend/app/dependencies/__init__.py
backend/app/dependencies/db.py
backend/app/main.py
backend/app/models/__init__.py
backend/app/models/user.py
backend/app/util/helper.py
backend/app/util/run_workflow.py
backend/app/util/workflow_orchestrator.py
backend/config/config.py
backend/database/schema.sql
backend/README.md
backend/requirements.txt
backend/setup.py
backend/tools/__init__.py
backend/tools/claude_tool.py
backend/tools/duckduckgo_tool.py
backend/tools/mysql_tool.py
backend/workflow_orchestrator.log
external-services/docker-compose.yml
frontend/.gitignore
frontend/app/[id]/graph_vizualize/page.tsx
frontend/app/api/analyze/route.ts
frontend/app/api/neo4j/nodes/[id]/route.ts
frontend/app/api/neo4j/relationships/[id]/route.ts
frontend/app/api/proposals/route.ts
frontend/app/globals.css
frontend/app/layout.tsx
frontend/app/loading.tsx
frontend/app/page.tsx
frontend/app/theme.ts
frontend/components/graph-controls.tsx
frontend/components/graph-legend.tsx
frontend/components/graph-stats.tsx
frontend/components/graph-visualization.tsx
frontend/components/node-details.tsx
frontend/components/ui/badge.tsx
frontend/components/ui/button.tsx
frontend/components/ui/card.tsx
frontend/hooks/use-graph-data.ts
frontend/lib/api-client.ts
frontend/lib/utils.ts
frontend/next.config.ts
frontend/package.json
frontend/postcss.config.mjs
frontend/README.md
frontend/tsconfig.json
frontend/types/graph.ts
frontend/types/neo4j.ts
README.md
run.sh
```

### Dependencies

- backend/requirements.txt: aiohttp@>=3.8.0, anthropic@>=0.3.0, asyncio, fastapi, pydantic, pydantic[email], pymongo, pytest@>=7.0.0, pytest-asyncio@>=0.21.0, python-dateutil@>=2.8.0, typing-extensions@>=4.0.0, uvicorn
- frontend/package.json: @emotion/cache@^11.11.0, @emotion/react@^11.11.0, @emotion/styled@^11.11.0, @mui/icons-material@^5.15.0, @mui/material@^5.15.0, @mui/material-nextjs@^5.15.0, @radix-ui/react-slot@^1.0.2, @tailwindcss/postcss@^4, @types/node@^20, @types/react@^19, @types/react-dom@^19, autoprefixer@^10.4.21, class-variance-authority@^0.7.0, clsx@^2.0.0, graphology@^0.26.0, lucide-react@^0.522.0, next@15.3.4, postcss@^8.5.6, react@^19.0.0, react-dom@^19.0.0, tailwind-merge@^2.0.0, tailwindcss@^4.1.10, typescript@^5, vis-network@^9.1.9

### Recent commits (newest first)

- Update README with tech stack and project details
- Enhance README with project overview and features
- added a script file to run the project
- integrated ollama changes
- changes
- key fix rajat's
- api key fix
- Merge branch 'master' of github.com:adityarao97/autonexus
- fix for raw materials
- test
- Merge branch 'master' of github.com:adityarao97/autonexus
- Updated prompt for raw materials
- graph color and ordering fixed
- Issues rectified.
- Corrected industry_context issue.
- Fixed timestamp issue
- Menu option changes.
- Merge branch 'master' of github.com:adityarao97/autonexus
- added deleted file
- Frontend and Backend changes.

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

### external-services/docker-compose.yml

```yaml
services:
  mongodb:
    image: mvertes/alpine-mongo:latest
    container_name: mongodb
    ports:
      - "27017:27017"
    volumes:
      - ./mongodb-data:/data/db
    restart: unless-stopped
```

### backend/requirements.txt

```
fastapi
uvicorn
pydantic
pydantic[email]
# Core dependencies - no MCP required
aiohttp>=3.8.0
asyncio
typing-extensions>=4.0.0
python-dateutil>=2.8.0

# Optional dependencies (install only if needed)
# aiomysql>=0.1.1  # Uncomment for real MySQL
anthropic>=0.3.0  # Uncomment for real Claude API

# Development dependencies (optional)
pytest>=7.0.0
pytest-asyncio>=0.21.0
pymongo
# tensorflow-gpu
```

### frontend/package.json

```
{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev --turbopack",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@mui/material": "^5.15.0",
    "@mui/icons-material": "^5.15.0",
    "@emotion/react": "^11.11.0",
    "@emotion/styled": "^11.11.0",
    "@radix-ui/react-slot": "^1.0.2",
    "class-variance-authority": "^0.7.0",
    "clsx": "^2.0.0",
    "graphology": "^0.26.0",
    "lucide-react": "^0.522.0",
    "next": "15.3.4",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "tailwind-merge": "^2.0.0",
    "vis-network": "^9.1.9",
    "@mui/material-nextjs": "^5.15.0",
    "@emotion/cache": "^11.11.0"
  },
  "devDependencies": {
    "@tailwindcss/postcss": "^4",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "autoprefixer": "^10.4.21",
    "postcss": "^8.5.6",
    "tailwindcss": "^4.1.10",
    "typescript": "^5"
  }
}

```

### backend/app/main.py

```python
from fastapi import FastAPI
from app.api.routes import router as api_router

app = FastAPI(title="My FastAPI App")

app.include_router(api_router, prefix="/api")

```

### frontend/app/layout.tsx

```typescript
import type React from "react"
import type { Metadata } from "next"
import { AppRouterCacheProvider } from "@mui/material-nextjs/v14-appRouter"
import { ThemeProvider } from "@mui/material/styles"
import CssBaseline from "@mui/material/CssBaseline"
import { theme } from "./theme"

export const metadata: Metadata = {
  title: "Neo4j Graph Visualization",
  description: "Interactive network graph powered by Neo4j and Next.js",
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        <AppRouterCacheProvider>
          <ThemeProvider theme={theme}>
            <CssBaseline />
            {children}
          </ThemeProvider>
        </AppRouterCacheProvider>
      </body>
    </html>
  )
}

```

### frontend/app/page.tsx

```typescript
"use client"

import { useState, useEffect } from "react"
import {
  Box,
  Container,
  Typography,
  Button,
  Card,
  CardContent,
  Grid,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  Paper,
  Chip,
  Dialog,
  DialogTitle,
  DialogContent,
  DialogActions,
  TextField,
  MenuItem,
  FormControl,
  InputLabel,
  Select,
  CircularProgress,
  Alert,
  IconButton,
} from "@mui/material"
import {
  Factory as FactoryIcon,
  Visibility,
  Add,
  Close,
  PlayArrow,
  CheckCircle,
  Schedule,
  Error as ErrorIcon,
} from "@mui/icons-material"
import Link from "next/link"

interface BusinessProposal {
  id: string
  industry_context: string
  destination_country: string
  priority: string
  status: "COMPLETED" | "processing" | "failed"
  created_at: string
  processed_at?: string
  node_count?: number
  relationship_count?: number
}

interface CreateProposalForm {
  industry_context: string
  destination_country: string
  priority: string
}

export default function HomePage() {
  const [proposals, setProposals] = useState<BusinessProposal[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [createDialogOpen, setCreateDialogOpen] = useState(false)
  const [processing, setProcessing] = useState(false)
  const [formData, setFormData] = useState<CreateProposalForm>({
    industry_context: "",
    destination_country: "",
    priority: "",
  })

  useEffect(() => {
    // Simulate API call
    const fetchProposals = async () => {
      try {
        setLoading(true)
        // Replace with actual API call
        const response = await fetch("/api/proposals")
        const data = await response.json()

        // Simulate delay
        await new Promise((resolve) => setTimeout(resolve, 1000))
        setProposals(data)
      } catch (err) {
        setError("Failed to fetch proposals")
      } finally {
        setLoading(false)
      }
    }

    fetchProposals()
  }, [])

  const handleCreateProposal = async () => {
    try {
      setProcessing(true)

      // Create proposal API call
      const response = await fetch("/api/analyze", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(formData),
      })

      if (!response.ok) {
        throw new Error("Failed to create proposal")
      }

      const newProposal = await response.json()

      // Add to proposals list
      setProposals((prev) => [newProposal, ...prev])

      // Reset form and close dialog
      setFormData({
        industry_context: "",
        destination_country: "",
        priority: "",
      })
      setCreateDialogOpen(false)
    } catch (err) {
      setError("Failed to create proposal")
    } finally {
      setProcessing(false)
    }
  }

  const getStatusIcon = (status: BusinessProposal["status"]) => {
    switch (status) {
      case "COMPLETED":
        return <CheckCircle color="success" />
      case "processing":
        return <Schedule color="warning" />
      case "failed":
        return <ErrorIcon color="error" />
    }
  }

  const getStatusColor = (status: BusinessProposal["status"]) => {
    switch (status) {
      case "COMPLETED":
        return "success"
      case "processing":
        return "warning"
      case "failed":
        return "error"
      default:
        return "default"
    }
  }

  const formatDate = (dateString: string) => {
    return new Date(dateString).toLocaleDateString("en-US", {
      year: "numeric",
      month: "short",
      day: "numeric",
      hour: "2-digit",
      minute: "2-digit",
    })
  }

  return (
    <Box sx={{ flexGrow: 1, minHeight: "100vh", bgcolor: "background.default" }}>
      <Container maxWidth="xl" sx={{ py: 4 }}>
        {/* Header */}
        <Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", mb: 4 }}>
          <Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
            <FactoryIcon sx={{ fontSize: 48, color: "primary.main" }} />
            <Box>
              <Typography variant="h3" component="h1" sx={{ fontWeight: 700 }}>
                Autonexus
              </Typography>
              <Typography variant="h6" color="text.secondary">
                Business proposal processing and supply chain visualization
              </Typography>
            </Box>
          </Box>
          <Button
            variant="contained"
            size="large"
            startIcon={<Add />}
            onClick={() => setCreateDialogOpen(true)}
            sx={{ px: 4, py: 1.5 }}
          >
            Create Proposal
          </Button>
        </Box>

        {/* Error Alert */}
        {error && (
          <Alert severity="error" sx={{ mb: 4 }} onClose={() => setError(null)}>
            {error}
          </Alert>
        )}

        {/* Statistics Cards */}
        <Grid container spacing={3} sx={{ mb: 4 }}>
          <Grid item xs={12} sm={6} md={3}>
            <Card>
              <CardContent>
                <Typography variant="h4" sx={{ fontWeight: "bold", color: "success.main" }}>
                  {proposals.filter((p) => p.status === "COMPLETED").length}
                </Typography>
                <Typography variant="body2" color="text.secondary">
                  Completed Proposals
                </Typography>
              </CardContent>
            </Card>
          </Grid>
          <Grid item xs={12} sm={6} md={3}>
            <Card>
              <CardContent>
                <Typography variant="h4" sx={{ fontWeight: "bold", color: "warning.main" }}>
                  {proposals.filter((p) => p.status === "processing").length}
                </Typography>
                <Typography variant="body2" color="text.secondary">
                  Processing
                </Typography>
              </CardContent>
            </Card>
          </Grid>
          <Grid item xs={12} sm={6} md={3}>
        
[truncated — 8375 more characters]
```

### frontend/app/api/analyze/route.ts

```typescript
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"

interface CreateProposalRequest {
  industry_context: string
  destination_country: string
  priority: string
}


export async function POST(request: NextRequest) {
  try {
    const body: CreateProposalRequest = await request.json()

    // Validate required fields
    if (!body.industry_context || !body.destination_country || !body.priority) {
      return NextResponse.json(
        { error: "Missing required fields: industry_context, destination_country, priority" },
        { status: 400 },
      )
    }

    // Send to FastAPI /analyze endpoint
    const response = await fetch(`http://127.0.0.1:8000/api/analyze`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        // Add any authentication headers if needed
        // 'Authorization': `Bearer ${process.env.API_TOKEN}`,
      },
      body: JSON.stringify({
        industry_context: body.industry_context,
        destination_country: body.destination_country,
        priority: body.priority,
      }),
    })

    if (!response.ok) {
      const errorText = await response.text()
      console.error("FastAPI analyze error:", errorText)
      throw new Error(`FastAPI analyze failed with status: ${response.status}`)
    }

    // Check if response is JSON
    const contentType = response.headers.get("content-type")
    if (!contentType || !contentType.includes("application/json")) {
      throw new Error("FastAPI did not return JSON response")
    }

    const data = await response.json()

    // Transform the response to match our frontend expectations
    const transformedData = {
      id: data._id || `${body.industry_context}-${body.destination_country}-${body.priority}-${Date.now()}`,
      industry: body.industry_context,
      destination: body.destination_country,
      priority: body.priority,
      status: "COMPLETED", // Since analyze endpoint processes immediately
      created: data.created ? new Date(data.created).toISOString().split("T")[0] : new Date().toISOString().split("T")[0],
      // Include the full analysis data for potential future use
      analysis_data: data,
    }

    return NextResponse.json(transformedData, { status: 201 })
  } catch (error) {
    console.error("Error calling FastAPI analyze endpoint:", error)

    // Return error response
    return NextResponse.json(
      {
        error: "Failed to analyze proposal",
        details: error instanceof Error ? error.message : "Unknown error occurred",
      },
      { status: 500 },
    )
  }
}

```

### frontend/app/api/proposals/route.ts

```typescript
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"

interface CreateProposalRequest {
  industry_context: string
  destination_country: string
  priority: string
}

export async function GET() {
  try {

    // Fetch proposals from FastAPI backend
    const response = await fetch(`http://127.0.0.1:8000/api/proposals`, {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
        // Add any authentication headers if needed
        // 'Authorization': `Bearer ${process.env.API_TOKEN}`,
      },
      // next: { revalidate: 30 }, // Revalidate every 30 seconds
    })

    if (!response.ok) {
      throw new Error(`FastAPI responded with status: ${response.status}`)
    }

    // Check if response is JSON
    const contentType = response.headers.get("content-type")
    if (!contentType || !contentType.includes("application/json")) {
      throw new Error("FastAPI did not return JSON response")
    }

    const data = await response.json()

    // Assuming FastAPI returns array of proposals or { proposals: [...] }
    const proposals = Array.isArray(data) ? data : data.proposals || []

    return NextResponse.json(proposals)
  } catch (error) {
    console.error("Error fetching proposals from FastAPI:", error)
  }
}

export async function POST(request: NextRequest) {
  try {
    const body: CreateProposalRequest = await request.json()

    // Validate required fields
    if (!body.industry_context || !body.destination_country || !body.priority) {
      return NextResponse.json(
        { error: "Missing required fields: industry_context, destination_country, priority" },
        { status: 400 },
      )
    }

    // Check if FastAPI base URL is configured
    if (!process.env.FASTAPI_BASE_URL) {
      // Return mock response for development
      const mockProposal = {
        id: `${body.industry_context}-${body.destination_country}-${body.priority}-${Date.now()}`,
        industry: body.industry_context,
        destination: body.destination_country,
        priority: body.priority,
        status: "processing",
        created: new Date().toISOString().split("T")[0],
      }

      console.warn("FASTAPI_BASE_URL not configured, returning mock proposal")
      return NextResponse.json(mockProposal, { status: 201 })
    }

    // Send to FastAPI backend for processing
    const response = await fetch(`http://127.0.0.1:8000/api/proposals`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        // Add any authentication headers if needed
        // 'Authorization': `Bearer ${process.env.API_TOKEN}`,
      },
      body: JSON.stringify(body),
    })

    if (!response.ok) {
      throw new Error(`FastAPI responded with status: ${response.status}`)
    }

    // Check if response is JSON
    const contentType = response.headers.get("content-type")
    if (!contentType || !contentType.includes("application/json")) {
      throw new Error("FastAPI did not return JSON response")
    }

    const data = await response.json()
    return NextResponse.json(data, { status: 201 })
  } catch (error) {
    console.error("Error creating proposal:", error)

    // Return mock response as fallback
    const body: CreateProposalRequest = await request.json()
    const mockProposal = {
      id: `${body.industry_context}-${body.destination_country}-${body.priority}-${Date.now()}`,
      industry: body.industry_context,
      destination: body.destination_country,
      priority: body.priority,
      status: "processing",
      created: new Date().toISOString().split("T")[0],
    }

    console.warn("Falling back to mock proposal due to FastAPI connection error")
    return NextResponse.json(mockProposal, { status: 201 })
  }
}

```

### frontend/app/[id]/graph_vizualize/page.tsx

```typescript
"use client"

import { use, useState } from "react"
import {
  Box,
  Container,
  Typography,
  Grid,
  Card,
  CardContent,
  AppBar,
  Toolbar,
  Chip,
  Avatar,
  Alert,
  Button,
} from "@mui/material"
import { Factory as FactoryIcon, NetworkCheck as NetworkIcon, FlashOn as FlashIcon, Refresh } from "@mui/icons-material"
import { GraphVisualization } from "@/components/graph-visualization"
import { GraphControls } from "@/components/graph-controls"
import { GraphStats } from "@/components/graph-stats"
import { NodeDetails } from "@/components/node-details"
import { GraphLegend } from "@/components/graph-legend"
import { useGraphData } from "@/hooks/use-graph-data"

interface PageProps {
  params: {
    id: string
  }
}

export default function GraphVisualizePage({ params }: PageProps) {
  const { id } = use(params) // Use React.use() to unwrap the Promise
  const [selectedNode, setSelectedNode] = useState<any>(null)
  const { data, loading, error, refetch } = useGraphData(id) // Pass id to hook

  const handleReset = () => {
    setSelectedNode(null)
  }

  const handleRefresh = async () => {
    setSelectedNode(null)
    await refetch()
  }

  return (
    <Box sx={{ flexGrow: 1, minHeight: "100vh", bgcolor: "background.default" }}>
      {/* Header */}
      <AppBar position="sticky" elevation={0} sx={{ bgcolor: "background.paper", color: "text.primary" }}>
        <Toolbar sx={{ py: 2 }}>
          <Avatar
            sx={{
              bgcolor: "primary.main",
              mr: 2,
              width: 48,
              height: 48,
            }}
          >
            <FactoryIcon />
          </Avatar>
          <Box sx={{ flexGrow: 1 }}>
            <Typography variant="h4" component="h1" sx={{ fontWeight: 700, mb: 0.5 }}>
              Supply Chain Visualization
            </Typography>
            <Typography variant="body2" color="text.secondary">
              Interactive visualization of raw material sourcing and supplier relationships
            </Typography>
          </Box>
          <Box sx={{ display: "flex", gap: 1 }}>
            <Chip
              icon={<NetworkIcon />}
              label={loading ? "Loading..." : "Supply Network"}
              color="primary"
              variant="filled"
            />
            <Chip icon={<FlashIcon />} label="Interactive" color="secondary" variant="outlined" />
            <Button variant="outlined" size="small" startIcon={<Refresh />} onClick={handleRefresh} disabled={loading}>
              Refresh
            </Button>
          </Box>
        </Toolbar>
      </AppBar>

      <Container maxWidth="xl" sx={{ py: 4 }}>
        {/* Global Error Alert */}
        {error && (
          <Alert
            severity="error"
            sx={{ mb: 4 }}
            action={
              <Button color="inherit" size="small" onClick={handleRefresh} startIcon={<Refresh />}>
                Retry
              </Button>
            }
          >
            Failed to load supply chain data: {error}
          </Alert>
        )}

        {/* Stats Row */}
        <Box sx={{ mb: 4 }}>
          <GraphStats stats={data?.stats} loading={loading} />
        </Box>

        {/* Main Content */}
        <Grid container spacing={3}>
          {/* Graph Visualization */}
          <Grid item xs={12} lg={8}>
            <Card sx={{ height: "100%" }}>
              <CardContent sx={{ p: 0, "&:last-child": { pb: 0 } }}>
                <Box sx={{ p: 3, borderBottom: 1, borderColor: "divider" }}>
                  <Box sx={{ display: "flex", alignItems: "center", gap: 1, mb: 1 }}>
                    <Box
                      sx={{
                        width: 8,
                        height: 8,
                        bgcolor: loading ? "grey.400" : "success.main",
                        borderRadius: "50%",
                        animation: loading ? "none" : "pulse 2s infinite",
                        "@keyframes pulse": {
                          "0%": { opacity: 1 },
                          "50%": { opacity: 0.5 },
                          "100%": { opacity: 1 },
                        },
                      }}
                    />
                    <Typography variant="h5" component="h2" sx={{ fontWeight: 600 }}>
                      Supply Chain Network
                    </Typography>
                  </Box>
                  <Typography variant="body2" color="text.secondary">
                    {loading
                      ? "Loading supply chain data..."
                      : "Raw material sourcing and supplier scoring visualization"}
                  </Typography>
                </Box>
                <Box sx={{ position: "relative" }}>
                  <GraphVisualization
                    nodes={data?.nodes || []}
                    relationships={data?.relationships || []}
                    loading={loading}
                    error={error}
                    onNodeSelect={setSelectedNode}
                    onRefresh={handleRefresh}
                  />
                </Box>
              </CardContent>
            </Card>
          </Grid>

          {/* Sidebar */}
          <Grid item xs={12} lg={4}>
            <Box sx={{ display: "flex", flexDirection: "column", gap: 3 }}>
              {/* Controls */}
              <GraphControls onReset={handleReset} />

              {/* Node Details */}
              <NodeDetails selectedNode={selectedNode} />

              {/* Legend */}
              <GraphLegend />
            </Box>
          </Grid>
        </Grid>
      </Container>
    </Box>
  )
}

```

### frontend/app/api/neo4j/relationships/[id]/route.ts

```typescript
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"


export async function GET(
  request: NextRequest, context: { params: Promise<{ id: string }> }
) {
  try {

    const { id } = await context.params
    // Fetch relationships from FastAPI backend
    const response = await fetch(`http://127.0.0.1:8000/api/neo4j/relationships/${id}`, {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
        // Add any authentication headers if needed
        // 'Authorization': `Bearer ${process.env.API_TOKEN}`,
      },
      // Add cache control if needed
      next: { revalidate: 60 }, // Revalidate every 60 seconds
    })

    if (!response.ok) {
      throw new Error(`FastAPI responded with status: ${response.status}`)
    }

    const data = await response.json()

    // Assuming FastAPI returns { relationships: [...] } or just [...]
    const relationships = Array.isArray(data) ? data : data.relationships

    return NextResponse.json({ relationships })
  } catch (error) {
    console.error("Error fetching relationships from FastAPI:", error)
    return NextResponse.json({ error: "Failed to fetch relationships from backend" }, { status: 500 })
  }
}

```

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