14 KiB
MAI - Monadical AI Container Tool
Overview
MAI (Monadical AI Container) is a command-line tool for managing ephemeral containers that run AI tools and development environments. It works with both local Docker and a dedicated remote web service that manages containers in a Docker-in-Docker (DinD) environment.
Technology Stack
MAI Service
- Web Framework: FastAPI for high-performance, async API endpoints
- Package Management: uv (Astral) for dependency management
- Database: SQLite for development, PostgreSQL for production
- Container Management: Docker SDK for Python
- Authentication: OAuth 2.0 integration with Authentik
MAI CLI
- Language: Python
- Package Management: uv for dependency management
- Distribution: Standalone binary via PyInstaller or similar
- Configuration: YAML for configuration files
System Architecture
Components
- CLI Tool (
mai): The command-line interface users interact with - MAI Service: A web service that handles remote container execution
- Container Drivers: Predefined container templates for various AI tools
Architecture Diagram
┌─────────────┐ ┌─────────────────────────┐
│ │ │ │
│ MAI CLI │◄─────────►│ Local Docker Daemon │
│ (mai) │ │ │
│ │ └─────────────────────────┘
└──────┬──────┘
│
│ REST API
│
┌──────▼──────┐ ┌─────────────────────────┐
│ │ │ │
│ MAI Service │◄─────────►│ Docker-in-Docker │
│ (Web API) │ │ │
│ │ └─────────────────────────┘
└─────────────┘
│
├──────────────┬───────────────┐
│ │ │
┌──────▼──────┐ ┌─────▼─────┐ ┌──────▼──────┐
│ │ │ │ │ │
│ Fluentd │ │ Langfuse │ │ Other │
│ Logging │ │ Logging │ │ Services │
│ │ │ │ │ │
└─────────────┘ └───────────┘ └─────────────┘
Core Concepts
- Session: An active container instance with a specific driver
- Driver: A predefined container template with specific AI tools installed
- Remote: A configured MAI service instance
CLI Tool Commands
Basic Commands
# Create a new session locally (shorthand)
mai
# List active sessions on local system
mai session list
# Create a new session locally
mai session create [OPTIONS]
# Create a session with a specific driver
mai session create --driver goose
# Create a session with a specific project repository
mai session create --driver goose --project github.com/hello/private
# Create a session with a project (shorthand)
mai git@github.com:hello/private
# Close a specific session
mai session close <id>
# Connect to an existing session
mai session connect <id>
# Stop the current session (from inside the container)
mai stop
Remote Management
# Add a remote MAI service
mai remote add <name> <url>
# List configured remote services
mai remote list
# Remove a remote service
mai remote remove <name>
# Authenticate with a remote service
mai -r <remote_name> auth
# Create a session on a remote service
mai -r <remote_name> [session create]
# List sessions on a remote service
mai -r <remote_name> session list
Environment Variables
# Set environment variables for a session
mai session create -e VAR1=value1 -e VAR2=value2
# Set environment variables for a remote session
mai -r <remote_name> session create -e VAR1=value1
Logging
# Stream logs from a session
mai session logs <id>
# Stream logs with follow option
mai session logs <id> -f
MAI Service Specification
Overview
The MAI Service is a web service that manages ephemeral containers in a Docker-in-Docker environment. It provides a REST API for container lifecycle management, authentication, and real-time log streaming.
API Endpoints
Authentication
POST /auth/login - Initiate Authentik authentication flow
POST /auth/callback - Handle Authentik OAuth callback
POST /auth/refresh - Refresh an existing token
POST /auth/logout - Invalidate current token
Authentik Integration
The MAI Service integrates with Authentik at https://authentik.monadical.io using OAuth 2.0:
-
Application Registration:
- MAI Service is registered as an OAuth application in Authentik
- Configured with redirect URI to
/auth/callback - Assigned appropriate scopes for user identification
-
Authentication Flow:
- User initiates authentication via CLI
- MAI CLI opens browser to Authentik authorization URL
- User logs in through Authentik's interface
- Authentik redirects to callback URL with authorization code
- MAI Service exchanges code for access and refresh tokens
- CLI receives and securely stores tokens
-
Token Management:
- Access tokens used for API authorization
- Refresh tokens used to obtain new access tokens
- Tokens are encrypted at rest in CLI configuration
Sessions
GET /sessions - List all sessions
POST /sessions - Create a new session
GET /sessions/{id} - Get session details
DELETE /sessions/{id} - Terminate a session
POST /sessions/{id}/connect - Establish connection to session
GET /sessions/{id}/logs - Stream session logs
Drivers
GET /drivers - List available drivers
GET /drivers/{name} - Get driver details
Projects
GET /projects - List all projects
POST /projects - Add a new project
GET /projects/{id} - Get project details
PUT /projects/{id} - Update project details
DELETE /projects/{id} - Remove a project
Service Configuration
# mai-service.yaml
server:
port: 3000
host: 0.0.0.0
docker:
socket: /var/run/docker.sock
network: mai-network
auth:
provider: authentik
url: https://authentik.monadical.io
clientId: mai-service
logging:
providers:
- type: fluentd
url: http://fluentd.example.com:24224
- type: langfuse
url: https://api.langfuse.com
apiKey: ${LANGFUSE_API_KEY}
drivers:
- name: goose
image: monadical/mai-goose:latest
env:
MCP_HOST: http://mcp:8000
- name: aider
image: monadical/mai-aider:latest
- name: claude-code
image: monadical/mai-claude-code:latest
projects:
storage:
type: encrypted
key: ${PROJECT_ENCRYPTION_KEY}
default_ssh_scan:
- github.com
- gitlab.com
- bitbucket.org
Docker-in-Docker Implementation
The MAI Service runs in a container with access to the host's Docker socket, allowing it to create and manage sibling containers. This approach provides:
- Isolation between containers
- Simple lifecycle management
- Resource constraints for security
Connection Handling
For remote connections to containers, the service provides two methods:
- WebSocket Terminal: Browser-based terminal access
- SSH Server: Each container runs an SSH server for CLI access
Logging Implementation
The MAI Service implements log collection and forwarding:
- Container logs are captured using Docker's logging drivers
- Logs are forwarded to configured providers (Fluentd, Langfuse)
- Real-time log streaming is available via WebSockets
Project Management
Adding Projects
Users can add projects with associated credentials:
# Add a project with SSH key
mai project add github.com/hello/private --ssh-key ~/.ssh/id_ed25519
# Add a project with token authentication
mai project add github.com/hello/private --token ghp_123456789
# List all projects
mai project list
# Remove a project
mai project remove github.com/hello/private
Project Configuration
Projects are stored in the MAI service and referenced by their repository URL. The configuration includes:
# Project configuration
id: github.com/hello/private
url: git@github.com:hello/private.git
type: git
auth:
type: ssh
key: |
-----BEGIN OPENSSH PRIVATE KEY-----
...encrypted key data...
-----END OPENSSH PRIVATE KEY-----
public_key: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...
Driver Implementation
Driver Structure
Each driver is a Docker image with a standardized structure:
/
├── entrypoint.sh # Container initialization
├── mai-init.sh # Standardized initialization script
├── mai-driver.yaml # Driver metadata and configuration
├── tool/ # AI tool installation
└── ssh/ # SSH server configuration
Standardized Initialization Script
All drivers include a standardized mai-init.sh script that handles common initialization tasks:
#!/bin/bash
# Project initialization
if [ -n "$MAI_PROJECT_URL" ]; then
echo "Initializing project: $MAI_PROJECT_URL"
# Set up SSH key if provided
if [ -n "$MAI_GIT_SSH_KEY" ]; then
mkdir -p ~/.ssh
echo "$MAI_GIT_SSH_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null
fi
# Set up token if provided
if [ -n "$MAI_GIT_TOKEN" ]; then
git config --global credential.helper store
echo "https://$MAI_GIT_TOKEN:x-oauth-basic@github.com" > ~/.git-credentials
fi
# Clone repository
git clone $MAI_PROJECT_URL /app
cd /app
# Run project-specific initialization if present
if [ -f "/app/.mai/init.sh" ]; then
bash /app/.mai/init.sh
fi
fi
# Driver-specific initialization continues...
Driver Configuration (mai-driver.yaml)
name: goose
description: Goose with MCP servers
version: 1.0.0
maintainer: team@monadical.com
init:
pre_command: /mai-init.sh
command: /entrypoint.sh
environment:
- name: MCP_HOST
description: MCP server host
required: true
default: http://localhost:8000
- name: GOOSE_ID
description: Goose instance ID
required: false
# Project environment variables
- name: MAI_PROJECT_URL
description: Project repository URL
required: false
- name: MAI_PROJECT_TYPE
description: Project repository type (git, svn, etc.)
required: false
default: git
- name: MAI_GIT_SSH_KEY
description: SSH key for Git authentication
required: false
sensitive: true
- name: MAI_GIT_TOKEN
description: Token for Git authentication
required: false
sensitive: true
ports:
- 8000 # Main application
- 22 # SSH server
volumes:
- mountPath: /app
description: Application directory
Example Built-in Drivers
- goose: Goose with MCP servers
- aider: Aider coding assistant
- claude-code: Claude Code environment
- custom: Custom Dockerfile support
Security Considerations
- Container Isolation: Each session runs in an isolated container
- Authentication: Integration with Authentik for secure authentication
- Resource Limits: Configurable CPU, memory, and storage limits
- Network Isolation: Internal Docker network for container-to-container communication
- Encrypted Connections: TLS for API connections and SSH for terminal access
Deployment
MAI Service Deployment
# docker-compose.yml for MAI Service
version: '3.8'
services:
mai-service:
image: monadical/mai-service:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./config:/app/config
ports:
- "3000:3000"
environment:
- AUTH_URL=https://authentik.monadical.io
- LANGFUSE_API_KEY=your_api_key
networks:
- mai-network
networks:
mai-network:
driver: bridge
Project Repository Integration Workflow
Adding a Project Repository
-
User adds project repository with authentication:
mai project add github.com/hello/private --ssh-key ~/.ssh/id_ed25519 -
MAI CLI reads the SSH key, encrypts it, and sends to MAI Service
-
MAI Service stores the project configuration securely
Using a Project in a Session
-
User creates a session with a project:
mai -r monadical git@github.com:hello/private -
MAI Service:
- Identifies the project from the URL
- Retrieves project authentication details
- Sets up environment variables:
MAI_PROJECT_URL=git@github.com:hello/private MAI_PROJECT_TYPE=git MAI_GIT_SSH_KEY=<contents of the SSH key> - Creates container with these environment variables
-
Container initialization:
- The standardized
mai-init.shscript detects the project environment variables - Sets up SSH key or token authentication
- Clones the repository to
/app - Runs any project-specific initialization scripts
- The standardized
-
User can immediately begin working with the repository
Implementation Roadmap
- Phase 1: Local CLI tool with Docker integration
- Phase 2: MAI Service REST API with basic container management
- Phase 3: Authentication and secure connections
- Phase 4: Project management functionality
- Phase 5: Driver implementation (Goose, Aider, Claude Code)
- Phase 6: Logging integration with Fluentd and Langfuse
- Phase 7: CLI remote connectivity improvements
- Phase 8: Additional drivers and extensibility features