Content
# AI MCP Server
> MCP Server for AI Image Generation + Gen-IP Minting Workflow
> Supports multiple AI providers (Google Gemini, OpenAI, Replicate, Stability AI), with Gemini as default
---
## 📑 Table of Contents
- [Quick Start](#-quick-start)
- [Install Dependencies](#1-install-dependencies)
- [Configure Environment Variables](#2-configure-environment-variables)
- [Start the Service](#3-start-the-service)
- [API Documentation](#-api-documentation)
- [Session Management](#1-session-management)
- [Image Generation](#2-image-generation)
- [Confirm and Stage](#3-confirm-and-stage-staging)
- [Admin API](#4-admin-api)
- [Supported AI Providers](#-supported-ai-providers-and-models)
- [Google Gemini](#google-gemini-default)
- [OpenAI DALL-E](#openai-dall-e)
- [Replicate](#replicate)
- [Stability AI](#stability-ai)
- [Complete Workflow Example](#-complete-workflow-example)
- [Environment Variables Configuration](#-environment-variables-configuration)
- [Database Overview](#-database-overview)
- [Testing](#-testing)
- [Production Deployment Guide](#-production-deployment-guide)
- [Error Handling](#-error-handling)
---
## 🚀 Quick Start
### 1. Install Dependencies
```bash
npm install
```
### 2. Configure Environment Variables
Copy the `.env` file and fill in your API Keys:
```bash
# Default provider (optional, defaults to gemini)
AI_PROVIDER=gemini
# Google Gemini (default provider)
GEMINI_API_KEY=your-gemini-api-key
# Optional: if not set, uses code default model (gemini-3-pro-image-preview)
GEMINI_MODEL=gemini-3-pro-image-preview
# OpenAI DALL-E
OPENAI_API_KEY=sk-your-openai-key
# Replicate
REPLICATE_API_TOKEN=your-replicate-token
# Stability AI
STABILITY_API_KEY=sk-your-stability-key
```
### 3. Start the Service
```bash
# Development mode (hot reload)
npm run dev
# Production mode
npm run build && npm start
```
The service runs on `http://localhost:3000` by default
---
## 📖 API Documentation
### Base URL
```
http://localhost:3000/api
```
---
### 1. Session Management
Sessions do not need to be created manually. When calling `/api/generate`:
- Without `session_id`: The service automatically creates a new session and returns the `session_id` in the response
- With `session_id`: Continue generating/iterating in the same session (Gemini supports multi-turn context)
Currently, no HTTP endpoints are exposed for retrieving session info or history.
---
### 2. Image Generation
#### Generate Image
```bash
POST /api/generate
Content-Type: application/json
{
"prompt": "a beautiful cat in the garden",
"provider": "gemini",
"model": "gemini-3-pro-image-preview",
"negative_prompt": "blurry, low quality",
"aspect_ratio": "16:9"
}
```
**Parameter Description:**
| Parameter | Required | Description |
|:----------|:--------:|:------------|
| `session_id` | ❌ | Optional, session ID; auto-created if not provided |
| `prompt` | ✅ | Generation prompt |
| `provider` | ❌ | AI provider: `gemini` (default) / `openai` / `replicate` / `stability` |
| `model` | ❌ | Model name (see supported models list below) |
| `negative_prompt` | ❌ | Negative prompt (content to exclude) |
| `aspect_ratio` | ❌ | Aspect ratio: `1:1` / `16:9` / `9:16` etc. |
**Response Example:**
```json
{
"image_url": "http://localhost:3000/temp/gen_xyz789.png",
"generation_id": "gen_xyz789",
"prompt": "a beautiful cat in the garden",
"provider": "gemini",
"model": "gemini-3-pro-image-preview",
"session_id": "sess_abc123",
"is_new_session": true,
"created_at": 1701504500000
}
```
generation_id is the identifier used to confirm the image and move it to staging.
#### Query Available Providers (Not Currently Exposed)
This HTTP endpoint is currently disabled; the functionality is retained in code (`src/routes/generate.ts`), uncomment to enable.
---
### 3. Confirm and Stage (Staging)
Confirm the generated image and upload to ICP on-chain storage, preparing for Gen-IP minting:
```bash
POST /api/session/confirm
Content-Type: application/json
{
"session_id": "sess_abc123",
"generation_id": "gen_xyz789",
"name": "My Beautiful Cat",
"description": "A cat in the garden"
}
```
**Response Example:**
```json
{
"id": "stg_abc123",
"name": "My Beautiful Cat",
"description": "A cat in the garden",
"image_url": "https://wgfis-kyaaa-aaaan-q2c3a-cai.raw.icp0.io/images/abc123xyz.png",
"prompt": "a beautiful cat in the garden",
"from": "ChatGPT",
"created_at": 1701504500000,
"expires_at": 1701590900000,
"status": "pending"
}
```
> **Note:**
> - Images are uploaded to on-chain canister storage, `image_url` returns an on-chain accessible URL. Falls back to local storage if ICP service is unavailable.
> - The `from` field identifies the calling source: `ChatGPT` (HTTPS API call) or `Claude` (MCP Tool call).
#### Preview Staged Image
After confirmation, the image URL varies by storage method:
| Storage Method | URL Format |
|:---------------|:-----------|
| **ICP On-chain** (default) | `https://{canister_id}.raw.icp0.io/images/{file_id}.png` |
| **Local Storage** (fallback) | `http://localhost:3000/uploads/{staging_id}.png` |
#### Query Staging Status
```bash
GET /api/staging?id=:staging_id
```
---
### 4. Admin API
Admin API is used for system management and monitoring, requires configuring `ADMIN_API_KEY` to use.
#### Authentication Method
Add `x-api-key` in the request header:
```bash
curl -H "x-api-key: your-admin-key" http://localhost:3000/api/admin/xxx
```
#### Get System Statistics
```bash
GET /api/admin/stats
```
**Response Example:**
```json
{
"active_sessions": 5,
"total_generations": 42,
"staging_total": 10,
"staging_pending": 7,
"staging_minted": 3
}
```
#### List All Active Sessions
```bash
GET /api/admin/sessions
```
**Response Example:**
```json
{
"sessions": [
{
"id": "sess_abc123",
"created_at": 1701504000000,
"expires_at": 1701507600000,
"generation_count": 3
}
]
}
```
#### List All Staged Images
```bash
GET /api/admin/staging
```
**Response Example:**
```json
{
"items": [
{
"id": "stg_xyz789",
"name": "My Gen-IP",
"status": "pending",
"image_url": "http://localhost:3000/uploads/stg_xyz789.png",
"created_at": 1701504500000
}
]
}
```
#### Delete Staged Image
```bash
DELETE /api/admin/staging?id=:staging_id
```
**Response Example:**
```json
{
"ok": true
}
```
#### Trigger Manual Cleanup
Clean up expired sessions, temporary files, and staged images:
```bash
POST /api/admin/cleanup
```
**Response Example:**
```json
{
"cleaned_sessions": 2,
"cleaned_temp_files": 5,
"cleaned_staging": 1
}
```
#### Security Notes
| Item | Description |
|:-----|:------------|
| Key Verification | Uses **constant-time comparison** to prevent timing attacks |
| Key Not Configured | Accessing admin endpoints returns `500` error |
| Invalid Key | Returns `401 Unauthorized` |
---
## 🤖 Supported AI Providers and Models
Recommended models and defaults are centralized in `src/config/models.ts`, can be overridden via environment variables (`GEMINI_MODEL` / `OPENAI_MODEL` / `REPLICATE_MODEL` / `STABILITY_MODEL` or generic `AI_MODEL`).
### Google Gemini (Default)
```bash
# Use Gemini default model (gemini-3-pro-image-preview)
curl -X POST http://localhost:3000/api/generate \
-H "Content-Type: application/json" \
-d '{
"session_id": "xxx",
"prompt": "a cat",
"provider": "gemini"
}'
# Specify Imagen 3 model
curl -X POST http://localhost:3000/api/generate \
-H "Content-Type: application/json" \
-d '{
"session_id": "xxx",
"prompt": "a cat",
"provider": "gemini",
"model": "imagen-3.0-generate-002"
}'
```
**Supported Models:**
| Model | Description |
|:------|:------------|
| `gemini-3-pro-image-preview` | Nano Banana Pro, latest high-quality image model (default) |
| `gemini-2.5-flash-image` | Nano Banana, fast image generation model |
| `gemini-2.0-flash-exp` | Legacy experimental model |
> Any Gemini/Imagen model that supports image generation can also be passed (e.g., `imagen-3.0-generate-002`).
### OpenAI DALL-E
```bash
# Use DALL-E-3 (default)
curl -X POST http://localhost:3000/api/generate \
-H "Content-Type: application/json" \
-d '{
"session_id": "xxx",
"prompt": "a cat",
"provider": "openai",
"model": "dall-e-3"
}'
# Use DALL-E-2 (cheaper)
curl -X POST http://localhost:3000/api/generate \
-H "Content-Type: application/json" \
-d '{
"session_id": "xxx",
"prompt": "a cat",
"provider": "openai",
"model": "dall-e-2"
}'
```
**Supported Models:**
| Model | Description | Price |
|:------|:------------|:------|
| `dall-e-3` | Latest model, best quality | $0.04-0.12/image |
| `dall-e-2` | Legacy model, cheaper | $0.016-0.02/image |
> Image editing endpoint defaults to `gpt-image-1` (can override with `model`, supports `gpt-image-1` / `dall-e-2`).
### Replicate
```bash
# Use Flux Schnell (free, recommended)
curl -X POST http://localhost:3000/api/generate \
-H "Content-Type: application/json" \
-d '{
"session_id": "xxx",
"prompt": "a cat",
"provider": "replicate",
"model": "black-forest-labs/flux-schnell"
}'
# Use SDXL
curl -X POST http://localhost:3000/api/generate \
-H "Content-Type: application/json" \
-d '{
"session_id": "xxx",
"prompt": "a cat",
"provider": "replicate",
"model": "stability-ai/sdxl"
}'
```
**Supported Models:**
| Model | Description |
|:------|:------------|
| `black-forest-labs/flux-schnell` | Fast and free (recommended) |
| `black-forest-labs/flux-dev` | High-quality development version |
| `black-forest-labs/flux-pro` | Professional version, highest quality |
| `stability-ai/sdxl` | Stable Diffusion XL |
| `stability-ai/stable-diffusion-3` | SD3 latest version |
| `bytedance/sdxl-lightning-4step` | 4-step fast generation |
| `lucataco/sdxl-lcm` | LCM fast generation |
| `playgroundai/playground-v2.5-1024px-aesthetic` | Artistic style |
> You can also pass any model ID on Replicate; the above are project built-in recommendations (see `src/config/models.ts`).
### Stability AI
```bash
# Use Stability AI
curl -X POST http://localhost:3000/api/generate \
-H "Content-Type: application/json" \
-d '{
"session_id": "xxx",
"prompt": "a cat",
"provider": "stability"
}'
```
**Supported Aspect Ratios:**
`16:9` · `1:1` · `21:9` · `2:3` · `3:2` · `4:5` · `5:4` · `9:16` · `9:21`
---
## 📋 Complete Workflow Example
### Command Line Quick Test (Production Environment)
```bash
# Production environment base URL
BASE_URL="https://vly-money-mcp-service.zkid.xyz"
# Health check
curl $BASE_URL/health
# Use Google Gemini (default); auto-creates session if session_id not provided
curl -X POST $BASE_URL/api/generate \
-H "Content-Type: application/json" \
-d '{"prompt": "a cat", "provider": "gemini"}'
# Use OpenAI DALL-E-3
curl -X POST $BASE_URL/api/generate \
-H "Content-Type: application/json" \
-d '{"prompt": "a cat", "provider": "openai", "model": "dall-e-3"}'
# Use Replicate Flux
curl -X POST $BASE_URL/api/generate \
-H "Content-Type: application/json" \
-d '{"prompt": "a cat", "provider": "replicate", "model": "black-forest-labs/flux-schnell"}'
# Use Stability AI
curl -X POST $BASE_URL/api/generate \
-H "Content-Type: application/json" \
-d '{"prompt": "a cat", "provider": "stability"}'
# Confirm image and move to staging (requires generation_id from generate endpoint response)
curl -X POST $BASE_URL/api/session/confirm \
-H "Content-Type: application/json" \
-d '{"session_id": "your_session_id", "generation_id": "your_generation_id", "name": "My Cat Image", "description": "A cute cat"}'
```
### Complete Shell Script Example
```bash
# 1. Generate image (auto-creates session if session_id not provided)
RESULT=$(curl -s -X POST http://localhost:3000/api/generate \
-H "Content-Type: application/json" \
-d "{
\"prompt\": \"a beautiful sunset over the ocean\",
\"provider\": \"gemini\",
\"aspect_ratio\": \"16:9\"
}")
SESSION=$(echo $RESULT | jq -r '.session_id')
IMAGE_URL=$(echo $RESULT | jq -r '.image_url')
GEN_ID=$(echo $RESULT | jq -r '.generation_id')
echo "Session: $SESSION"
echo "Image URL: $IMAGE_URL"
echo "Generation ID: $GEN_ID"
# 2. Preview image (open in browser)
open "$IMAGE_URL"
# 3. Confirm and stage
STAGING=$(curl -s -X POST "http://localhost:3000/api/session/confirm" \
-H "Content-Type: application/json" \
-d "{
\"session_id\": \"$SESSION\",
\"generation_id\": \"$GEN_ID\",
\"name\": \"Sunset Over Ocean\",
\"description\": \"A beautiful sunset view\"
}")
STAGING_ID=$(echo $STAGING | jq -r '.id')
STAGING_URL=$(echo $STAGING | jq -r '.image_url')
echo "Staging ID: $STAGING_ID"
echo "Staging URL: $STAGING_URL"
# 4. Check staging status
curl -s "http://localhost:3000/api/staging?id=$STAGING_ID" | jq
```
---
## 📁 Image Access Paths
| Stage | Storage Location | Path Format | Description |
|:------|:-----------------|:------------|:------------|
| Generating | Local temporary | `http://localhost:3000/temp/{generation_id}.png` | Temporary storage, cleaned up after session expires |
| Confirmed | **ICP On-chain** | `https://{canister_id}.raw.icp0.io/images/{file_id}.png` | Permanent on-chain storage |
| Confirmed (fallback) | Local | `http://localhost:3000/uploads/{staging_id}.png` | Local storage when ICP unavailable |
### ICP On-chain Storage Overview
This project defaults to using **ICP (Internet Computer)** as permanent image storage:
- **Decentralized Storage**: Images stored on ICP blockchain with high availability and durability
- **Chunked Upload**: Supports large file chunked uploads, each chunk defaults to 500KB
- **HTTP Gateway Access**: Images directly accessible via `raw.icp0.io` domain, no additional proxy needed
- **Auto Fallback**: Falls back to local storage automatically if ICP service is unavailable
Configure ICP storage (`.env`):
```bash
ICP_ENABLED=true # Enable ICP storage
ICP_HOST=https://ic0.app # ICP mainnet
ICP_ASSETS_CANISTER_ID=wgfis-kyaaa-aaaan-q2c3a-cai # Your Canister ID
```
---
## ⚙️ Environment Variables Configuration
```bash
# ============================================================
# Server Configuration
# ============================================================
PORT=3000
NODE_ENV=development
BASE_URL=http://localhost:3000
# ============================================================
# Storage Configuration
# ============================================================
UPLOAD_DIR=./uploads
TEMP_DIR=./temp
# ============================================================
# TTL Configuration
# ============================================================
SESSION_TTL_HOURS=50 # Session validity period
STAGING_TTL_HOURS=24 # Staging validity period
# ============================================================
# Limit Configuration
# ============================================================
PROMPT_MAX_LENGTH=400 # Maximum prompt length
GLOBAL_GENERATIONS_PER_MIN=10 # Global generations per minute limit
SESSION_GENERATION_LIMIT=20 # Per-session generation limit
FILE_SIZE_LIMIT=10485760 # File size limit (10MB)
# ============================================================
# AI Provider Configuration
# ============================================================
AI_PROVIDER=gemini # Default provider
# Google Gemini (default)
GEMINI_API_KEY=your-gemini-api-key
# Optional: if not set, uses code default model (gemini-3-pro-image-preview)
GEMINI_MODEL=gemini-3-pro-image-preview
# OpenAI
OPENAI_API_KEY=sk-xxx
OPENAI_MODEL=dall-e-3
# Replicate
REPLICATE_API_TOKEN=xxx
REPLICATE_MODEL=black-forest-labs/flux-schnell
# Stability AI
STABILITY_API_KEY=sk-xxx
# ============================================================
# Admin Configuration
# ============================================================
ADMIN_API_KEY=your-secret-key
# ============================================================
# ICP On-chain Storage Configuration
# ============================================================
ICP_ENABLED=true # Enable ICP storage (default true)
ICP_HOST=https://ic0.app # ICP network host (default mainnet)
ICP_ASSETS_CANISTER_ID=wgfis-kyaaa-aaaan-q2c3a-cai # Asset storage Canister ID
ICP_CHUNK_SIZE=512000 # Chunk size (default 500KB)
# ============================================================
# SQLite Database Configuration
# ============================================================
DB_PATH=./data/mcp.db # Database file path
DB_WAL_MODE=true # Enable WAL mode (improves concurrent performance)
DB_IN_MEMORY=false # Use in-memory database (for testing)
```
---
## 💾 Database Overview
This project uses **SQLite** as data storage, with high-performance synchronous operations via the `better-sqlite3` library.
### Database Features
| Feature | Description |
|:--------|:------------|
| **WAL Mode** | Enables Write-Ahead Logging, supports concurrent reads, writes don't block reads |
| **Prepared Statements** | All common SQL statements pre-compiled, avoiding repeated parsing overhead |
| **Auto Persistence** | Data automatically written to disk, no manual save required |
| **Transaction Support** | Batch operations use transactions to ensure data consistency |
| **Foreign Key Constraints** | Foreign key constraints enabled, automatically cascade delete related data |
### Database Table Structure
```
sessions # User sessions
├── id # Session ID
├── created_at # Creation time
└── expires_at # Expiration time
generations # Image generation records
├── id # Generation ID
├── session_id # Associated session (foreign key)
├── prompt # Prompt
├── image_url # Image URL
└── ...
staging # Gen-IP staging records
├── id # Staging ID
├── name # Gen-IP name
├── status # Status (pending/minted)
└── ...
```
### Performance Optimization
- **Index Optimization**: Indexes created on frequently queried fields like `expires_at`, `session_id`, `status`
- **Batch Operations**: Use transactions for batch insert/update, reducing disk I/O
- **Connection Reuse**: Singleton database connection, avoiding repeated connection creation overhead
### Database Maintenance
```bash
# Check database size
ls -lh ./data/mcp.db
# Optimize database file (reclaim space)
sqlite3 ./data/mcp.db "VACUUM"
# View table structure
sqlite3 ./data/mcp.db ".schema"
# View data statistics
sqlite3 ./data/mcp.db "SELECT COUNT(*) FROM sessions; SELECT COUNT(*) FROM staging;"
```
---
## 🧪 Testing
This project uses **Vitest** as the testing framework, providing comprehensive unit and integration tests.
### Run Tests
```bash
# Run all tests
npm test
# Watch mode (recommended during development)
npm run test:watch
# Generate coverage report
npm run test:coverage
# Visual test interface
npm run test:ui
```
### Test Coverage
| Module | Test File | Test Count | Description |
|:-------|:----------|:----------:|:------------|
| Utilities | `tests/unit/utils/*.test.ts` | 55 | ID generation, error handling, image size calculation |
| Middleware | `tests/unit/middleware/*.test.ts` | 25 | Rate limiting, Admin API authentication, daily rate limiting |
| Database | `tests/unit/db/index.test.ts` | 46 | Session/Generation/Staging CRUD, transactions, indexes |
| API Routes | `tests/unit/routes/*.test.ts` | 49 | Session, Staging, Admin, Generate, Edit API tests |
| AI Services | `tests/unit/services/*.test.ts` | 30 | AI providers, Gemini Rate Limiter |
**Total: 205 tests**
### Test File Structure
```
tests/
├── unit/
│ ├── utils/
│ │ ├── id.test.ts # ID generation function tests
│ │ ├── errors.test.ts # Error classes and utility function tests
│ │ └── image.test.ts # Image size calculation tests
│ ├── middleware/
│ │ ├── auth.test.ts # Admin API authentication tests
│ │ ├── rateLimit.test.ts # Rate limiting tests
│ │ └── dailyRateLimit.test.ts # Daily rate limiting tests
│ ├── db/
│ │ └── index.test.ts # SQLite database operation tests
│ ├── routes/
│ │ ├── session.test.ts # Session API tests
│ │ ├── staging.test.ts # Staging API tests
│ │ ├── admin.test.ts # Admin API tests
│ │ ├── generate.test.ts # Generate API tests
│ │ └── edit.test.ts # Edit API tests
│ └── services/
│ ├── ai.test.ts # AI provider tests
│ ├── gemini-rate-limiter.test.ts # Gemini Rate Limiter tests
│ └── gemini-provider.test.ts # Gemini Provider tests
├── fixtures/
│ └── mocks.ts # Mock data and helper functions
└── setup.ts # Test configuration and initialization
```
### Test Configuration
Test configuration is in `vitest.config.ts`:
| Config Item | Value |
|:------------|:------|
| Environment | Node.js |
| Isolation | Each test file runs independently |
| Parallel | Uses forks multi-process pool (avoids native module conflicts) |
| Timeout | 10 seconds |
| Database | Uses SQLite in-memory mode during tests |
### Writing New Tests
```typescript
import { describe, it, expect, beforeEach, vi } from 'vitest';
describe('Feature Module', () => {
beforeEach(() => {
// Setup before tests
});
it('should correctly execute some functionality', () => {
// Test code
expect(result).toBe(expected);
});
});
```
---
## 🚢 Production Deployment Guide
### 1. Requirements
| Requirement | Minimum |
|:------------|:--------|
| Node.js | >= 18.x |
| npm | >= 9.x |
| Disk Space | 1GB+ |
| Memory | 512MB+ |
### 2. Production Environment Configuration
Copy `.env.example` and modify for production:
```bash
cp .env.example .env
```
**Required Configuration Changes:**
| Config Item | Development Value | Production Value | Description |
|:------------|:------------------|:-----------------|:------------|
| `NODE_ENV` | `development` | `production` | **Must change** |
| `BASE_URL` | `http://localhost:3000` | `https://your-domain.com` | **Must change** |
| `ADMIN_API_KEY` | empty | strong password | **Must set** |
<details>
<summary><b>📄 Complete Production Configuration Example (Click to expand)</b></summary>
```bash
# ============================================================
# Basic Configuration
# ============================================================
PORT=3000
NODE_ENV=production
BASE_URL=https://your-domain.com
# ============================================================
# Storage Configuration
# ============================================================
UPLOAD_DIR=./uploads
TEMP_DIR=./temp
# ============================================================
# TTL Configuration (can be extended for production)
# ============================================================
SESSION_TTL_HOURS=50
STAGING_TTL_HOURS=72
# ============================================================
# Rate Limiting Configuration (adjust based on server performance)
# ============================================================
PROMPT_MAX_LENGTH=400
GLOBAL_GENERATIONS_PER_MIN=30
SESSION_GENERATION_LIMIT=50
FILE_SIZE_LIMIT=10485760
# ============================================================
# AI Providers (configure at least one)
# ============================================================
AI_PROVIDER=gemini
# Google Gemini (default)
GEMINI_API_KEY=your-production-gemini-key
# Optional: if not set, uses code default model (gemini-3-pro-image-preview)
GEMINI_MODEL=gemini-3-pro-image-preview
# OpenAI
OPENAI_API_KEY=sk-your-production-key
OPENAI_MODEL=dall-e-3
# Replicate
REPLICATE_API_TOKEN=your-production-token
REPLICATE_MODEL=black-forest-labs/flux-schnell
# Stability AI
STABILITY_API_KEY=sk-your-production-key
# ============================================================
# Security Configuration (must set!)
# ============================================================
ADMIN_API_KEY=your-strong-secret-key-at-least-32-chars
# ============================================================
# SQLite Database Configuration
# ============================================================
DB_PATH=./data/mcp.db
DB_WAL_MODE=true
```
</details>
### 3. Deployment Methods
<details>
<summary><b>Method 1: Direct Deployment</b></summary>
```bash
# 1. Clone repository
git clone https://github.com/your-repo/mcp_server.git
cd mcp_server
# 2. Install production dependencies
npm install --production
# 3. Create necessary directories
mkdir -p uploads temp data
# 4. Set directory permissions
chmod 755 uploads temp data
# 5. Configure environment variables
cp .env.example .env
# Edit .env file, set production configuration
# 6. Build project
npm run build
# 7. Start service
npm start
```
</details>
<details>
<summary><b>Method 2: Using PM2 (Recommended)</b></summary>
PM2 is a process manager for Node.js, supporting auto-restart, load balancing, log management, and more.
```bash
# 1. Install PM2 globally
npm install -g pm2
# 2. Build project
npm run build
# 3. Start with PM2
pm2 start dist/index.js --name "mcp-server" --env production
# 4. Check status
pm2 status
# 5. View logs
pm2 logs mcp-server
# 6. Set up auto-start on boot
pm2 save
pm2 startup
```
**PM2 Configuration File (Optional)**
Create `ecosystem.config.js`:
```javascript
module.exports = {
apps: [{
name: 'mcp-server',
script: 'dist/index.js',
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '1G',
env_production: {
NODE_ENV: 'production'
}
}]
};
```
Start with config file:
```bash
pm2 start ecosystem.config.js --env production
```
</details>
<details>
<summary><b>Method 3: Using Docker</b></summary>
**Dockerfile:**
```dockerfile
FROM node:18-alpine
WORKDIR /app
# Copy dependency files
COPY package*.json ./
# Install production dependencies
RUN npm install --production
# Copy source code
COPY . .
# Build
RUN npm run build
# Create storage directories
RUN mkdir -p uploads temp data
# Expose port
EXPOSE 3000
# Start command
CMD ["node", "dist/index.js"]
```
**docker-compose.yml:**
```yaml
version: '3.8'
services:
mcp-server:
build: .
ports:
- "3000:3000"
volumes:
- ./uploads:/app/uploads
- ./temp:/app/temp
- ./data:/app/data
env_file:
- .env
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
```
Run:
```bash
# Build and start
docker-compose up -d
# View logs
docker-compose logs -f
# Stop
docker-compose down
```
</details>
### 4. Reverse Proxy Configuration
<details>
<summary><b>Nginx Configuration</b></summary>
```nginx
server {
listen 80;
server_name your-domain.com;
# Redirect to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name your-domain.com;
# SSL certificate configuration
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Upload file size limit
client_max_body_size 20M;
# Proxy configuration
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 300s;
}
# Static resource caching
location /uploads/ {
proxy_pass http://127.0.0.1:3000/uploads/;
proxy_cache_valid 200 7d;
add_header Cache-Control "public, max-age=604800";
}
location /temp/ {
proxy_pass http://127.0.0.1:3000/temp/;
proxy_cache_valid 200 1h;
add_header Cache-Control "public, max-age=3600";
}
}
```
</details>
<details>
<summary><b>Caddy Configuration (Simpler)</b></summary>
```caddyfile
your-domain.com {
reverse_proxy localhost:3000
# Static resource caching
@static path /uploads/* /temp/*
header @static Cache-Control "public, max-age=86400"
}
```
</details>
### 5. Health Check and Monitoring
```bash
# Check if service is running
curl http://localhost:3000/health
# Expected response
{"status":"ok","provider":"gemini","mcp_sessions":0}
# Get system statistics (requires ADMIN_API_KEY)
curl -H "x-api-key: your-admin-key" https://your-domain.com/api/admin/stats
```
### 6. Backup Strategy
```bash
# Method 1: Direct copy database file (recommended when service is stopped)
cp ./data/mcp.db ./backup/mcp-$(date +%Y%m%d).db
# Method 2: Online backup using sqlite3 command (safe while service is running)
sqlite3 ./data/mcp.db ".backup './backup/mcp-$(date +%Y%m%d).db'"
# Method 3: Full backup (including image files)
tar -czf backup-$(date +%Y%m%d).tar.gz uploads data
```
**Set up scheduled backup (crontab):**
```bash
# Daily backup at 2 AM
0 2 * * * sqlite3 /app/data/mcp.db ".backup '/backup/mcp-$(date +\%Y\%m\%d).db'"
# Weekly full backup (including images)
0 3 * * 0 tar -czf /backup/mcp-full-$(date +\%Y\%m\%d).tar.gz /app/uploads /app/data
```
### 7. Security Checklist
Please verify before deployment:
- [ ] `NODE_ENV` set to `production`
- [ ] `BASE_URL` set to correct production domain
- [ ] `ADMIN_API_KEY` set with sufficient complexity (32+ characters recommended)
- [ ] All API Keys using production environment keys
- [ ] HTTPS enabled
- [ ] Reverse proxy configured
- [ ] Appropriate rate limiting parameters set
- [ ] Log persistence configured
- [ ] Scheduled backups set up
- [ ] Health check endpoint tested
### 8. Common Issues
| Issue | Solution |
|:------|:---------|
| Image URL returns localhost | Check if `BASE_URL` is correctly set to production domain |
| Admin API returns 500 error | Verify `ADMIN_API_KEY` environment variable is set |
| Data lost after service restart | Verify `data` directory exists and has write permissions |
| Image generation fails | Check if AI provider's API Key is valid and account balance |
---
## ❌ Error Handling
API returns standard HTTP status codes and JSON error responses:
| Status Code | Description |
|:-----------:|:------------|
| 400 | Bad request parameters |
| 404 | Resource not found (session expired, staging not found, etc.) |
| 429 | Rate limit exceeded |
| 500 | Internal server error |
**Error Response Format:**
```json
{
"error": "Session expired or not found",
"code": "SESSION_EXPIRED",
"details": {
"session_id": "sess_abc123"
}
}
```
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available