Changes:
- Create Gitea workflow for ai-stack-deployer
- Trigger on main branch (default branch)
- Use oussamadouhou + REGISTRY_TOKEN for authentication
- Build from ./Dockerfile
This enables :latest tag creation via {{is_default_branch}}.
Tags created:
- git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:latest
- git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:<sha>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
12 KiB
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)
{
"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.
# 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:
{
"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 fromdeploy_stack
Returns:
{
"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 deploymentcreating_dns- Creating DNS recordscreating_project- Creating Dokploy projectcreating_application- Creating applicationdeploying- Deploying containercompleted- Successfully deployedfailed- Deployment failed
3. list_deployments
List all recent deployments.
Parameters: None
Returns:
{
"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:
{
"available": true,
"valid": true,
"name": "john"
}
Or if invalid:
{
"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:
{
"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:
# 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
- Check
.mcp.jsonexists in the project root - Restart Claude Code completely
- Check for syntax errors in
.mcp.json - Ensure Bun is installed and in PATH
Tools Not Working
-
Check environment variables in
.env:cat .env -
Test API connections:
bun run src/test-clients.ts -
Check Dokploy token (common issue):
- Navigate to https://deploy.intra.flexinit.nl
- Settings → Profile → API Tokens
- Generate new token if expired
Deployment Fails
- DNS issues: Verify Hetzner API token is valid
- Dokploy issues: Verify Dokploy API token and URL
- Name conflicts: Check if name already exists
- 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:
- Variables from
.envfile (loaded by Bun) - 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:
delete_stack- Remove a deployed stackget_stack_logs- Retrieve application logsrestart_stack- Restart a deployed stacklist_available_images- Show available Docker imagesget_stack_metrics- Show resource usage
Production Deployment
- Add authentication to the MCP server
- Rate limiting for deployments
- Persistent storage for deployment state (currently in-memory)
- Webhooks for deployment status updates
- Audit logging for all operations
Technical Details
Protocol Used
- Transport: stdio (standard input/output)
- Message Format: JSON-RPC 2.0
- SDK:
@modelcontextprotocol/sdkv1.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:
{
"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:
- Check this guide first
- Review
TESTING.mdfor API connection issues - Check Claude Code logs:
~/.config/claude/debug/ - Test API clients directly:
bun run src/test-clients.ts
Built with ❤️ by Oussama Douhou