# AI Stack Deployer - MCP Server Guide

## Overview

This project now includes a **Model Context Protocol (MCP) Server** that exposes deployment functionality to Claude Code and other MCP-compatible clients.

### What is MCP?

The Model Context Protocol is a standardized way for AI assistants to interact with external tools and services. By implementing an MCP server, this project allows Claude Code to:

- Deploy new AI stacks programmatically
- Check deployment status
- Verify name availability
- Test API connections
- List all deployments

---

## Architecture

```
┌──────────────────────────────────────────────────────────────┐
│                 CLAUDE CODE (MCP Client)                      │
│  - Discovers available tools                                  │
│  - Calls tools with parameters                                │
│  - Receives structured responses                              │
└────────────────────────┬─────────────────────────────────────┘
                         │
                         │ MCP Protocol (stdio)
                         │
┌────────────────────────▼─────────────────────────────────────┐
│          AI Stack Deployer MCP Server                         │
│          (src/mcp-server.ts)                                  │
│                                                               │
│  Available Tools:                                             │
│  ✓ deploy_stack                                               │
│  ✓ check_deployment_status                                    │
│  ✓ list_deployments                                           │
│  ✓ check_name_availability                                    │
│  ✓ test_api_connections                                       │
└────────────────────────┬─────────────────────────────────────┘
                         │
                         │ Uses existing API clients
                         │
┌────────────────────────▼─────────────────────────────────────┐
│         Existing Infrastructure                               │
│  - Hetzner DNS API (src/api/hetzner.ts)                       │
│  - Dokploy API (src/api/dokploy.ts)                           │
└───────────────────────────────────────────────────────────────┘
```

---

## What Was Created

### 1. MCP Server Implementation (`src/mcp-server.ts`)

A fully-functional MCP server that:
- Integrates with existing Hetzner and Dokploy API clients
- Validates stack names according to project rules
- Tracks deployment state in memory
- Handles errors gracefully
- Returns structured JSON responses

### 2. Project Configuration (`.mcp.json`)

```json
{
  "mcpServers": {
    "ai-stack-deployer": {
      "command": "bun",
      "args": ["run", "src/mcp-server.ts"],
      "env": {}
    }
  }
}
```

This file tells Claude Code how to start the MCP server.

### 3. Package Script (`package.json`)

Added `"mcp": "bun run src/mcp-server.ts"` to scripts for easy testing.

---

## How to Enable in Claude Code

### Step 1: Restart Claude Code

After creating the `.mcp.json` file, you need to restart Claude Code for it to discover the MCP server.

```bash
# If Claude Code is running, exit and restart
opencode
```

### Step 2: Approve the MCP Server

When Claude Code starts in this directory, it will detect the `.mcp.json` file and prompt you to approve the MCP server.

**You'll see a prompt like:**
```
Found MCP server configuration:
- ai-stack-deployer

Would you like to enable this MCP server? (y/n)
```

Type `y` to approve.

### Step 3: Verify MCP Server is Running

Claude Code will automatically start the MCP server when needed. You can verify it's working by asking Claude Code:

```
Can you list the available MCP tools?
```

You should see the 5 tools from the AI Stack Deployer.

---

## Available Tools

### 1. `deploy_stack`

Deploys a new AI coding assistant stack.

**Parameters:**
- `name` (string, required): Username for the stack (3-20 chars, lowercase alphanumeric and hyphens)

**Returns:**
```json
{
  "success": true,
  "deploymentId": "dep_1704830000000_abc123",
  "name": "john",
  "status": "completed",
  "url": "https://john.ai.flexinit.nl",
  "message": "Stack successfully deployed at https://john.ai.flexinit.nl"
}
```

**Example usage in Claude Code:**
```
Deploy an AI stack for user "alice"
```

---

### 2. `check_deployment_status`

Check the status of a deployment.

**Parameters:**
- `deploymentId` (string, required): The deployment ID from `deploy_stack`

**Returns:**
```json
{
  "success": true,
  "deployment": {
    "id": "dep_1704830000000_abc123",
    "name": "john",
    "status": "completed",
    "url": "https://john.ai.flexinit.nl",
    "createdAt": "2026-01-09T17:30:00.000Z"
  }
}
```

**Possible statuses:**
- `initializing` - Starting deployment
- `creating_dns` - Creating DNS records
- `creating_project` - Creating Dokploy project
- `creating_application` - Creating application
- `deploying` - Deploying container
- `completed` - Successfully deployed
- `failed` - Deployment failed

---

### 3. `list_deployments`

List all recent deployments.

**Parameters:** None

**Returns:**
```json
{
  "success": true,
  "deployments": [
    {
      "id": "dep_1704830000000_abc123",
      "name": "john",
      "status": "completed",
      "url": "https://john.ai.flexinit.nl",
      "createdAt": "2026-01-09T17:30:00.000Z"
    }
  ],
  "total": 1
}
```

---

### 4. `check_name_availability`

Check if a stack name is available and valid.

**Parameters:**
- `name` (string, required): The name to check

**Returns:**
```json
{
  "available": true,
  "valid": true,
  "name": "john"
}
```

Or if invalid:
```json
{
  "available": false,
  "valid": false,
  "error": "Name must be between 3 and 20 characters"
}
```

---

### 5. `test_api_connections`

Test connections to Hetzner DNS and Dokploy APIs.

**Parameters:** None

**Returns:**
```json
{
  "hetzner": {
    "success": true,
    "message": "Connected to Hetzner Cloud DNS API. Zone \"flexinit.nl\" has 75 RRSets.",
    "recordCount": 75,
    "zoneName": "flexinit.nl"
  },
  "dokploy": {
    "success": true,
    "message": "Connected to Dokploy API. Found 12 projects.",
    "projectCount": 12
  },
  "overall": true
}
```

---

## Testing the MCP Server

### Manual Test (Direct Invocation)

You can test the MCP server directly:

```bash
# Start the MCP server
bun run mcp

# It will wait for JSON-RPC messages on stdin
# Press Ctrl+C to exit
```

### Test via Claude Code

Once enabled in Claude Code, you can test it by asking:

```
Test the API connections for the AI Stack Deployer
```

Claude Code will invoke the `test_api_connections` tool and show you the results.

---

## Troubleshooting

### MCP Server Not Appearing in Claude Code

1. **Check `.mcp.json` exists** in the project root
2. **Restart Claude Code** completely
3. **Check for syntax errors** in `.mcp.json`
4. **Ensure Bun is installed** and in PATH

### Tools Not Working

1. **Check environment variables** in `.env`:
   ```bash
   cat .env
   ```

2. **Test API connections**:
   ```bash
   bun run src/test-clients.ts
   ```

3. **Check Dokploy token** (common issue):
   - Navigate to https://deploy.intra.flexinit.nl
   - Settings → Profile → API Tokens
   - Generate new token if expired

### Deployment Fails

1. **DNS issues**: Verify Hetzner API token is valid
2. **Dokploy issues**: Verify Dokploy API token and URL
3. **Name conflicts**: Check if name already exists
4. **Permissions**: Ensure API tokens have required permissions

---

## Security Considerations

### Environment Variables

The MCP server inherits environment variables from the parent process. The `.mcp.json` file has an empty `env` object, which means it will use:

1. Variables from `.env` file (loaded by Bun)
2. Variables from the shell environment

**Never commit** `.env` file to version control!

### API Token Safety

- Hetzner and Dokploy API tokens are read from environment variables
- Tokens are never exposed in MCP responses
- All API calls are authenticated

---

## Integration Examples

### Example 1: Deploy Stack from Claude Code

```
User: Deploy an AI stack for user "bob"

Claude: I'll deploy an AI stack for "bob" using the deploy_stack tool.
[Calls deploy_stack with name="bob"]

Result:
✓ Deployment successful!
- Deployment ID: dep_1704830000000_xyz789
- URL: https://bob.ai.flexinit.nl
- Status: completed
```

### Example 2: Check All Deployments

```
User: Show me all recent deployments

Claude: I'll list all deployments using the list_deployments tool.
[Calls list_deployments]

Result:
Total: 3 deployments
1. alice - https://alice.ai.flexinit.nl (completed)
2. bob - https://bob.ai.flexinit.nl (completed)
3. charlie - https://charlie.ai.flexinit.nl (failed)
```

### Example 3: Validate Name Before Deploying

```
User: Can I use the name "test" for a new stack?

Claude: Let me check if "test" is available.
[Calls check_name_availability with name="test"]

Result: ❌ Name "test" is reserved and cannot be used.
Reserved names: admin, api, www, root, system, test, demo, portal
```

---

## Next Steps

### Enhance the MCP Server

Consider adding these tools:

1. **`delete_stack`** - Remove a deployed stack
2. **`get_stack_logs`** - Retrieve application logs
3. **`restart_stack`** - Restart a deployed stack
4. **`list_available_images`** - Show available Docker images
5. **`get_stack_metrics`** - Show resource usage

### Production Deployment

1. **Add authentication** to the MCP server
2. **Rate limiting** for deployments
3. **Persistent storage** for deployment state (currently in-memory)
4. **Webhooks** for deployment status updates
5. **Audit logging** for all operations

---

## Technical Details

### Protocol Used

- **Transport**: stdio (standard input/output)
- **Message Format**: JSON-RPC 2.0
- **SDK**: `@modelcontextprotocol/sdk` v1.25.2

### State Management

Currently, deployment state is stored in-memory using a `Map`:
- ✅ Fast access
- ✅ Simple implementation
- ❌ Lost on server restart
- ❌ Not shared across instances

For production, consider:
- Redis for distributed state
- PostgreSQL for persistent storage
- File-based storage for simplicity

### Error Handling

The MCP server wraps all tool calls in try-catch blocks and returns structured errors:

```json
{
  "success": false,
  "error": "Name already taken"
}
```

This ensures Claude Code always receives parseable responses.

---

## Summary

✅ **MCP Server**: Fully implemented in `src/mcp-server.ts`
✅ **Configuration**: Added `.mcp.json` for Claude Code
✅ **Tools**: 5 tools for deployment management
✅ **Integration**: Uses existing API clients
✅ **Testing**: Server starts successfully
✅ **Documentation**: This guide

**You can now use Claude Code to deploy and manage AI stacks through natural language commands!**

---

## Support

For issues or questions:
1. Check this guide first
2. Review `TESTING.md` for API connection issues
3. Check Claude Code logs: `~/.config/claude/debug/`
4. Test API clients directly: `bun run src/test-clients.ts`

---

**Built with ❤️ by Oussama Douhou**
