A full-stack multimodal AI chat application with Model Context Protocol (MCP) support. Built with React (TanStack Router/Query) on the frontend and FastAPI on the backend.
- Multimodal Chat: Support for text, images, audio, and PDF inputs
- Multiple AI Models: Choose from various models via OpenRouter API
- Streaming Responses: Real-time streaming of AI responses
- MCP Integration: Tool usage with approval workflows
- Model Capabilities: Automatic detection and display of model capabilities
- Clean Architecture: Well-organized codebase with separation of concerns
nova-demo-app/
βββ backend/ # FastAPI backend
β βββ app.py # Main FastAPI application
β βββ models/ # Pydantic models
β β βββ schemas.py # Request/response schemas
β βββ routers/ # API route handlers
β β βββ chat.py # Chat endpoints
β β βββ mcp.py # MCP endpoints
β βββ services/ # Business logic
β β βββ chat_service.py # Chat service
β β βββ mcp_service.py # MCP service
β βββ mcp_client_fastmcp.py # MCP client implementation
β βββ utils.py # Utility functions
β
βββ nova-demo-frontend/ # React frontend
β βββ src/
β β βββ components/ # React components
β β β βββ ChatHeader.tsx # Model selection & MCP controls
β β β βββ ChatMessages.tsx # Message display
β β β βββ ChatInput.tsx # Input area with file uploads
β β β βββ MessageContent.tsx # Markdown message renderer
β β β βββ ModelSelector.tsx # Model dropdown with search
β β β βββ ModelCapabilities.tsx # Capability badges
β β β βββ MCPControls.tsx # MCP configuration
β β β βββ ToolApprovalModal.tsx # Tool approval dialog
β β β βββ FilePreview.tsx # File upload previews
β β β βββ Header.tsx # App header
β β β βββ Spinner.tsx # Loading spinner
β β β
β β βββ hooks/ # Custom React hooks
β β β βββ useAvailableModels.ts # Fetch models
β β β βββ useChatStreaming.ts # Streaming chat
β β β βββ useMCP.ts # MCP integration
β β β βββ useToolApproval.ts # Tool approval logic
β β β
β β βββ types/ # TypeScript type definitions
β β β βββ chat.ts # Chat-related types
β β β
β β βββ utils/ # Utility functions
β β β βββ modelCapabilities.ts # Model capability checks
β β β βββ fileHandlers.ts # File upload handlers
β β β βββ streamParser.ts # Streaming response parser
β β β
β β βββ routes/ # TanStack Router routes
β β βββ index.tsx # Main chat route
β β
β βββ package.json # Frontend dependencies
β
βββ infra/ # Infrastructure code
β βββ flux.py # Flux model integration
β βββ wan2.py # Wan2 model integration
β
βββ docker-compose.yml # Docker composition
The backend follows a clean, modular architecture:
- FastAPI application initialization
- CORS middleware configuration
- Router registration
- Health check endpoint
-
chat.py: Handles all chat-related endpoints/chat: Simple non-streaming chat/chat_streaming: Streaming chat with MCP support/mcp/approve_tool_calls_streaming: Tool approval workflow
-
mcp.py: MCP management endpoints/mcp/servers: List available MCP servers/mcp/tools/{server_type}: Get tools for a server/mcp/cleanup: Cleanup MCP connections
-
chat_service.py: Core chat logic- Message formatting for OpenRouter API
- Streaming response handling
- Tool call accumulation and execution
-
mcp_service.py: MCP client management- Re-exports the global
mcp_manager - Provides clean import path
- Re-exports the global
schemas.py: Pydantic models for validationMessage: Chat message with multimodal supportChatRequest: Chat endpoint requestToolCallApprovalRequest: Tool approval requestImageData,AudioData,PdfData: File data models
utils.py: Model management and OpenRouter integrationmcp_client_fastmcp.py: FastMCP client implementation
The frontend uses modern React patterns with TanStack:
Modular, reusable UI components:
- ChatHeader: Model selection, capabilities display, MCP controls
- ChatMessages: Message list with auto-scroll
- ChatInput: Input field with file upload buttons
- ModelSelector: Searchable model dropdown
- ToolApprovalModal: Modal for approving tool usage
- FilePreview: Image/audio/PDF preview components
Encapsulate business logic and state management:
- useAvailableModels: Fetches and caches model list
- useChatStreaming: Manages streaming chat with message parsing
- useMCP: Handles MCP server and tool fetching
- useToolApproval: Manages tool approval workflow
TypeScript interfaces for type safety:
- Message, Model, ToolCall types
- File data types (Image, Audio, PDF)
- API request/response types
Pure functions for common operations:
- modelCapabilities.ts: Check model support for features
- fileHandlers.ts: Validate and process file uploads
- streamParser.ts: Parse streaming JSON responses
TanStack Router pages:
- index.tsx: Main chat interface (now clean and organized!)
- Backend: Python 3.11+, uv or pip
- Frontend: Node.js 18+, Bun or npm
- API Key: OpenRouter API key
Create a .env file in the backend/ directory:
API_KEY=your_openrouter_api_key_here
CMU_API_MCP_URL=http://localhost:8000/mcp # Optional: MCP server URLcd backend
# Install dependencies (using uv)
uv sync
# Or using pip
pip install -r requirements.txt
# Run the server
uvicorn app:app --reload --host 0.0.0.0 --port 8000cd nova-demo-frontend
# Install dependencies
bun install # or npm install
# Set environment variable
echo "VITE_API_URL=http://localhost:8000" > .env
# Run development server
bun dev # or npm run dev# Build and run with Docker Compose
docker-compose up --buildThe app supports multiple input types:
- Text: Standard chat messages
- Images: For vision models (automatic detection)
- Audio: For speech-to-text models
- PDFs: Document analysis via OpenRouter's file parser
Models are automatically tagged with capability badges:
- ποΈ Can view images: Supports image input
- π΅ Can process audio: Supports audio input
- π Can process PDFs: PDF support (all models via plugin)
- π¨ Can generate images: Image generation capability
MCP enables AI models to use external tools:
- Server Management: Connect to different MCP servers
- Tool Discovery: Automatically list available tools
- Approval Workflow: Optional manual approval for tool calls
- Auto-Approval: Streamline workflow with automatic approval
Real-time streaming for better UX:
- Character-by-character streaming
- Proper JSON parsing for incomplete chunks
- Image detection in streaming responses
- Tool call detection and handling
The codebase follows best practices:
- TypeScript: Full type safety on frontend
- Type Hints: Python type hints throughout backend
- Separation of Concerns: Clear module boundaries
- Documentation: Comprehensive docstrings and comments
- Error Handling: Graceful error handling and user feedback
- Define Pydantic models in
models/schemas.py - Create service logic in
services/ - Add routes in
routers/ - Register router in
app.py
- Define types in
types/ - Create utilities in
utils/ - Build custom hooks in
hooks/ - Create components in
components/ - Use in routes
Once running, visit:
- API Docs: http://localhost:8000/docs
- Alternative Docs: http://localhost:8000/redoc
Contributions are welcome! Please follow the existing code structure and style.
[Your License Here]
- OpenRouter: AI model routing
- FastAPI: Modern Python web framework
- TanStack: React Query and Router
- FastMCP: Model Context Protocol implementation