# 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**