DEPLOYMENT_GUIDE.md•14.4 kB
# Tableau MCP Server - Deployment Guide
**Phase 6: Cloud Run Deployment**
**Version**: 1.0
**Last Updated**: November 18, 2025
---
## Table of Contents
1. [Overview](#overview)
2. [Prerequisites](#prerequisites)
3. [Environment Setup](#environment-setup)
4. [Secrets Management](#secrets-management)
5. [Staging Deployment](#staging-deployment)
6. [Production Deployment](#production-deployment)
7. [Verification & Testing](#verification--testing)
8. [Rollback Procedures](#rollback-procedures)
9. [Troubleshooting](#troubleshooting)
10. [Cost Management](#cost-management)
---
## Overview
This guide covers deploying the Tableau MCP Server to Google Cloud Run with two environments:
- **Staging**: Testing environment with lower resource limits and scale-to-zero capability
- **Production**: Production environment with guaranteed availability and higher resources
Both environments use:
- Google Cloud Run for serverless deployment
- Google Secret Manager for credential management
- Google Container Registry for Docker images
- Regional deployment in `australia-southeast1`
---
## Prerequisites
### Required Software
1. **gcloud CLI** (v450.0.0+)
```bash
# Install
curl https://sdk.cloud.google.com | bash
# Verify
gcloud version
```
2. **Docker** (v24.0.0+)
```bash
# Verify
docker --version
```
3. **Git** (for version control)
```bash
git --version
```
### Google Cloud Setup
1. **Active Google Cloud Project**
- Billing enabled
- Project ID ready
2. **Required IAM Permissions**
- `roles/run.admin` - Cloud Run management
- `roles/iam.serviceAccountUser` - Service account usage
- `roles/storage.admin` - Container Registry
- `roles/secretmanager.admin` - Secret management
3. **Enabled APIs**
- Cloud Run API
- Container Registry API
- Secret Manager API
- Cloud Build API (optional, for CI/CD)
### Tableau Requirements
1. **Tableau Cloud or Server Access**
- Admin or appropriate permissions
- Ability to create Personal Access Tokens
2. **Personal Access Token (PAT)**
- Separate PATs for staging and production recommended
- Token name and value recorded securely
---
## Environment Setup
### 1. Configure gcloud CLI
```bash
# Authenticate
gcloud auth login
# Set project
gcloud config set project YOUR_PROJECT_ID
# Set default region
gcloud config set run/region australia-southeast1
# Verify configuration
gcloud config list
```
### 2. Enable Required APIs
```bash
gcloud services enable \
run.googleapis.com \
containerregistry.googleapis.com \
secretmanager.googleapis.com \
cloudbuild.googleapis.com
```
### 3. Configure Docker Authentication
```bash
gcloud auth configure-docker
```
---
## Secrets Management
Before deploying, set up secrets for both environments.
### Automated Setup (Recommended)
```bash
# Make script executable
chmod +x create-secrets.sh
# Create staging secrets
./create-secrets.sh staging
# Create production secrets (when ready)
./create-secrets.sh production
```
### Manual Setup
See [SECRETS_SETUP.md](SECRETS_SETUP.md) for detailed instructions.
### Verify Secrets
```bash
# List secrets
gcloud secrets list --filter="labels.app=tableau-mcp"
# Verify staging secrets
gcloud secrets describe tableau-token-staging
gcloud secrets describe mcp-api-key-staging
# Verify production secrets
gcloud secrets describe tableau-token-production
gcloud secrets describe mcp-api-key-production
```
---
## Staging Deployment
### Automated Deployment (Recommended)
```bash
# Make deployment script executable
chmod +x deploy-staging.sh
# Run deployment
./deploy-staging.sh
```
The script will:
1. ✅ Verify prerequisites
2. ✅ Enable required APIs
3. ✅ Build Docker image
4. ✅ Push to Google Container Registry
5. ✅ Verify secrets exist
6. ✅ Deploy to Cloud Run
7. ✅ Test health endpoints
8. ✅ Display service URL and API key
### Manual Deployment
If you prefer manual control:
```bash
# 1. Build image
PROJECT_ID=$(gcloud config get-value project)
IMAGE_NAME="gcr.io/$PROJECT_ID/tableau-mcp:staging-latest"
docker build -t $IMAGE_NAME . --platform linux/amd64
# 2. Push image
docker push $IMAGE_NAME
# 3. Deploy to Cloud Run
gcloud run deploy tableau-mcp-staging \
--image=$IMAGE_NAME \
--platform=managed \
--region=australia-southeast1 \
--allow-unauthenticated \
--min-instances=0 \
--max-instances=5 \
--cpu=1 \
--memory=512Mi \
--timeout=300 \
--concurrency=80 \
--set-env-vars="NODE_ENV=staging,PORT=8080,TABLEAU_SERVER_URL=YOUR_URL,TABLEAU_SITE_ID=YOUR_SITE,TABLEAU_TOKEN_NAME=YOUR_TOKEN_NAME,TABLEAU_API_VERSION=3.23" \
--set-secrets="TABLEAU_TOKEN_VALUE=tableau-token-staging:latest,MCP_API_KEY=mcp-api-key-staging:latest"
```
### Post-Deployment
```bash
# Get service URL
SERVICE_URL=$(gcloud run services describe tableau-mcp-staging \
--region=australia-southeast1 \
--format='value(status.url)')
echo "Staging URL: $SERVICE_URL"
# Test health endpoint
curl $SERVICE_URL/health
# Get API key for Cursor
gcloud secrets versions access latest --secret=mcp-api-key-staging
```
---
## Production Deployment
### Important Notes
⚠️ **Production deployment requires extra caution:**
- Uses production Tableau credentials
- Runs with minimum 1 instance (higher cost)
- Higher resource limits (2 CPU, 1Gi memory)
- Requires separate API key from staging
### Automated Deployment (Recommended)
```bash
# Make deployment script executable
chmod +x deploy-production.sh
# Run deployment
./deploy-production.sh
```
The script will:
1. ⚠️ Require explicit confirmation (type "yes")
2. ✅ Verify prerequisites
3. ✅ Build Docker image with production tag
4. ✅ Push to Google Container Registry
5. ✅ Verify production secrets exist
6. ✅ Deploy to Cloud Run with production config
7. ✅ Test health endpoints
8. ✅ Display service URL and production API key
### Manual Deployment
```bash
# 1. Build image
PROJECT_ID=$(gcloud config get-value project)
IMAGE_NAME="gcr.io/$PROJECT_ID/tableau-mcp:production-latest"
docker build -t $IMAGE_NAME . --platform linux/amd64
# 2. Push image
docker push $IMAGE_NAME
# 3. Deploy to Cloud Run
gcloud run deploy tableau-mcp-production \
--image=$IMAGE_NAME \
--platform=managed \
--region=australia-southeast1 \
--allow-unauthenticated \
--min-instances=1 \
--max-instances=10 \
--cpu=2 \
--memory=1Gi \
--timeout=300 \
--concurrency=100 \
--set-env-vars="NODE_ENV=production,PORT=8080,TABLEAU_SERVER_URL=YOUR_URL,TABLEAU_SITE_ID=YOUR_SITE,TABLEAU_TOKEN_NAME=YOUR_TOKEN_NAME,TABLEAU_API_VERSION=3.23" \
--set-secrets="TABLEAU_TOKEN_VALUE=tableau-token-production:latest,MCP_API_KEY=mcp-api-key-production:latest"
```
---
## Verification & Testing
### Health Check Endpoints
Test all health endpoints:
```bash
SERVICE_URL="YOUR_SERVICE_URL"
# Basic health check
curl $SERVICE_URL/health
# Expected: {"status":"healthy","timestamp":"..."}
# Readiness check
curl $SERVICE_URL/ready
# Expected: {"status":"ready","tableau":"connected","timestamp":"..."}
# Liveness check
curl $SERVICE_URL/alive
# Expected: {"status":"alive","uptime":...,"timestamp":"..."}
```
### MCP Endpoint Test
Test MCP SSE endpoint (requires API key):
```bash
# Without API key (should fail)
curl $SERVICE_URL/sse
# Expected: 401 Unauthorized
# With API key (should connect)
curl -H "X-API-Key: YOUR_API_KEY" $SERVICE_URL/sse
# Expected: Server-Sent Events stream
```
### Comprehensive Testing
See [TEST_DEPLOYMENT.md](TEST_DEPLOYMENT.md) for full testing checklist.
---
## Rollback Procedures
### List Revisions
```bash
# Staging
gcloud run revisions list \
--service=tableau-mcp-staging \
--region=australia-southeast1
# Production
gcloud run revisions list \
--service=tableau-mcp-production \
--region=australia-southeast1
```
### Rollback to Previous Revision
```bash
# Get revision name from list above
REVISION_NAME="tableau-mcp-staging-00001" # Example
# Rollback staging
gcloud run services update-traffic tableau-mcp-staging \
--region=australia-southeast1 \
--to-revisions=$REVISION_NAME=100
# Rollback production
gcloud run services update-traffic tableau-mcp-production \
--region=australia-southeast1 \
--to-revisions=$REVISION_NAME=100
```
### Rollback with Gradual Traffic Split
For production, use gradual rollback:
```bash
# Split traffic 50/50 between old and new
gcloud run services update-traffic tableau-mcp-production \
--region=australia-southeast1 \
--to-revisions=REVISION_OLD=50,REVISION_NEW=50
# Monitor for issues...
# Complete rollback if needed
gcloud run services update-traffic tableau-mcp-production \
--region=australia-southeast1 \
--to-revisions=REVISION_OLD=100
```
---
## Troubleshooting
### Issue: Docker Build Fails
**Symptom**: `docker build` command fails
**Solutions**:
```bash
# 1. Check Docker is running
docker ps
# 2. Clean up old images
docker system prune -a
# 3. Build with verbose output
docker build -t IMAGE_NAME . --progress=plain
# 4. Check Dockerfile syntax
cat Dockerfile
```
### Issue: Image Push Fails
**Symptom**: `docker push` fails with authentication error
**Solutions**:
```bash
# 1. Re-authenticate Docker
gcloud auth configure-docker
# 2. Check project ID is correct
gcloud config get-value project
# 3. Verify Container Registry API is enabled
gcloud services list --enabled | grep containerregistry
```
### Issue: Secret Not Found
**Symptom**: Deployment fails with "secret not found"
**Solutions**:
```bash
# 1. List all secrets
gcloud secrets list
# 2. Create missing secrets
./create-secrets.sh staging # or production
# 3. Verify secret names match exactly
gcloud secrets describe tableau-token-staging
```
### Issue: Health Check Fails
**Symptom**: Service deployed but health check returns 500
**Solutions**:
```bash
# 1. View logs
gcloud run logs read tableau-mcp-staging --region=australia-southeast1 --limit=50
# 2. Check environment variables
gcloud run services describe tableau-mcp-staging --region=australia-southeast1 --format=json | jq '.spec.template.spec.containers[0].env'
# 3. Verify Tableau connectivity
# Check TABLEAU_SERVER_URL is correct
# Verify PAT is valid and not expired
```
### Issue: MCP Endpoint Returns 401
**Symptom**: MCP SSE endpoint always returns 401
**Solutions**:
```bash
# 1. Verify API key is set correctly
gcloud secrets versions access latest --secret=mcp-api-key-staging
# 2. Test with explicit API key
curl -H "X-API-Key: YOUR_KEY" $SERVICE_URL/sse
# 3. Check server logs for authentication errors
gcloud run logs read tableau-mcp-staging --region=australia-southeast1 | grep "authentication"
```
### Issue: Service Won't Start
**Symptom**: Cloud Run shows service as unhealthy
**Solutions**:
```bash
# 1. View detailed logs
gcloud run logs read SERVICE_NAME --region=australia-southeast1 --limit=100
# 2. Check startup time
# Increase startup probe initialDelaySeconds if needed
# 3. Test locally
docker run -p 8080:8080 --env-file .env.staging IMAGE_NAME
# 4. Verify PORT environment variable
# Cloud Run requires PORT=8080
```
---
## Cost Management
### Staging Cost Optimization
Staging is configured to scale to zero when not in use:
```bash
# Verify min instances is 0
gcloud run services describe tableau-mcp-staging \
--region=australia-southeast1 \
--format='value(spec.template.metadata.annotations[autoscaling.knative.dev/minScale])'
# Expected: 0
```
**Staging Costs**: ~$5-15/month (scales to zero when idle)
### Production Cost Monitoring
Production runs with minimum 1 instance for availability:
```bash
# View current resource allocation
gcloud run services describe tableau-mcp-production \
--region=australia-southeast1 \
--format='value(spec.template.spec.containers[0].resources.limits)'
# Monitor request count
gcloud logging read "resource.type=cloud_run_revision AND resource.labels.service_name=tableau-mcp-production" \
--limit=100 \
--format=json | jq length
```
**Production Costs**: ~$40-65/month (always-on service)
### Cost Reduction Tips
1. **Use staging for development** - Keep production clean
2. **Monitor logs** - Reduce log retention period
3. **Optimize image size** - Smaller images = faster cold starts
4. **Review metrics** - Adjust min/max instances based on actual usage
---
## Updating Services
### Update Staging
```bash
# Redeploy with latest code
./deploy-staging.sh
```
### Update Production (Gradual Rollout)
```bash
# Deploy new version
./deploy-production.sh
# Traffic splits automatically to new revision
# Monitor for issues
# Rollback if needed (see Rollback Procedures)
```
### Update Environment Variables Only
```bash
# Update without redeploying
gcloud run services update tableau-mcp-staging \
--region=australia-southeast1 \
--set-env-vars="NEW_VAR=value"
```
### Update Secrets
```bash
# Add new version to secret
echo -n "NEW_VALUE" | \
gcloud secrets versions add SECRET_NAME --data-file=-
# Cloud Run automatically uses latest version
# Redeploy service to pick up new secret
./deploy-staging.sh
```
---
## Next Steps
After successful deployment:
1. ✅ **Verify all endpoints** - Test health, ready, alive, and SSE
2. ✅ **Configure Cursor** - Create MCP configuration (Phase 7)
3. ✅ **Test MCP tools** - Verify all 9 tools work correctly
4. ✅ **Set up monitoring** - See [MONITORING_GUIDE.md](MONITORING_GUIDE.md)
5. ✅ **Document credentials** - Store API keys securely
6. ✅ **Schedule maintenance** - Secret rotation every 90 days
---
## Support & Resources
### Cloud Run Documentation
- [Cloud Run Overview](https://cloud.google.com/run/docs)
- [Cloud Run Pricing](https://cloud.google.com/run/pricing)
- [Troubleshooting Guide](https://cloud.google.com/run/docs/troubleshooting)
### Tableau API Documentation
- [Tableau REST API Reference](https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api.htm)
- [Personal Access Tokens](https://help.tableau.com/current/server/en-us/security_personal_access_tokens.htm)
### Project Documentation
- [IMPLEMENTATION_PLAN.md](IMPLEMENTATION_PLAN.md) - Full project plan
- [PASS_OFF.md](PASS_OFF.md) - Implementation status
- [PHASE_6_LOG.md](PHASE_6_LOG.md) - Phase 6 details
---
**Deployment Guide Version**: 1.0
**Last Updated**: November 18, 2025
**Contact**: See project documentation for support