1
+ name : Build and Deploy MCP to GKE
2
+
3
+ on :
4
+ push :
5
+ branches :
6
+ - master
7
+ workflow_dispatch :
8
+ inputs :
9
+ deployment_name :
10
+ description : ' Deployment Name'
11
+ required : true
12
+ default : ' mcp-git-commands'
13
+
14
+ env :
15
+ PROJECT_ID : ${{ secrets.GKE_PROJECT }}
16
+ GKE_CLUSTER : ruh-ai-dev-cluster # Add your cluster name here
17
+ GKE_ZONE : us-central1 # Add your cluster zone here
18
+ DEPLOYMENT_NAME : ${{ github.event.inputs.deployment_name || 'mcp-server' }}
19
+ MCP_IMAGE_NAME : mcp-git-commands
20
+ REPOSITORY : mcp-server # Artifact Registry repository name
21
+ REGION : us-central1 # Artifact Registry region
22
+
23
+ jobs :
24
+ setup-build-publish-deploy :
25
+ name : Setup, Build, Publish, and Deploy
26
+ runs-on : ubuntu-latest
27
+ environment : production
28
+
29
+ permissions :
30
+ contents : ' read'
31
+ id-token : ' write'
32
+
33
+ steps :
34
+ - name : Checkout
35
+ uses : actions/checkout@v4
36
+
37
+ # Setup gcloud CLI
38
+ - name : Authenticate to Google Cloud
39
+ uses : google-github-actions/auth@v2
40
+ with :
41
+ credentials_json : ${{ secrets.GKE_SA_KEY }}
42
+
43
+ # # Create Artifact Registry repository if it doesn't exist
44
+ # - name: Create Artifact Registry Repository
45
+ # run: |-
46
+ # gcloud artifacts repositories create $REPOSITORY \
47
+ # --repository-format=docker \
48
+ # --location=$REGION \
49
+ # --description="MCP Server images repository" \
50
+ # --quiet || true
51
+
52
+ # Configure Docker to use the gcloud command-line tool as a credential helper for Artifact Registry
53
+ - run : |-
54
+ gcloud --quiet auth configure-docker $REGION-docker.pkg.dev
55
+
56
+ # Get the GKE credentials so we can deploy to the cluster
57
+ - name : Get GKE Credentials
58
+ uses : google-github-actions/get-gke-credentials@v2
59
+ with :
60
+ cluster_name : ${{ env.GKE_CLUSTER }}
61
+ location : ${{ env.GKE_ZONE }}
62
+
63
+ # Build the Docker image for MCP server
64
+ - name : Build MCP Server Image
65
+ run : |-
66
+ docker build \
67
+ --no-cache \
68
+ --tag "$REGION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$MCP_IMAGE_NAME:${GITHUB_REF_NAME}-${GITHUB_SHA::7}" \
69
+ --build-arg GITHUB_SHA="$GITHUB_SHA" \
70
+ --build-arg GITHUB_REF="$GITHUB_REF" \
71
+ .
72
+
73
+ # Push the Docker image to Google Artifact Registry
74
+ - name : Publish MCP Server Image
75
+ run : |-
76
+ docker push "$REGION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$MCP_IMAGE_NAME:${GITHUB_REF_NAME}-${GITHUB_SHA::7}"
77
+
78
+ # Create deployment manifest
79
+ - name : Create deployment manifest
80
+ run : |
81
+ cat > k8s-manifest.yaml << 'EOF'
82
+ apiVersion: apps/v1
83
+ kind: Deployment
84
+ metadata:
85
+ name: ${{ env.DEPLOYMENT_NAME }}
86
+ labels:
87
+ app: ${{ env.DEPLOYMENT_NAME }}
88
+ spec:
89
+ replicas: 1
90
+ selector:
91
+ matchLabels:
92
+ app: ${{ env.DEPLOYMENT_NAME }}
93
+ template:
94
+ metadata:
95
+ labels:
96
+ app: ${{ env.DEPLOYMENT_NAME }}
97
+ spec:
98
+ containers:
99
+ # MCP Server (stdio) - using the image we just built and pushed to GCR
100
+ - name: mcp-server
101
+ image: ${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.REPOSITORY }}/${{ env.MCP_IMAGE_NAME }}:$GITHUB_REF_NAME-${GITHUB_SHA::7}
102
+ # Keep their original command/entrypoint
103
+ # The container runs normally with stdio
104
+ env:
105
+ - name: GITHUB_TOKEN
106
+ valueFrom:
107
+ secretKeyRef:
108
+ name: mcp-secrets
109
+ key: github-token
110
+ optional: true
111
+ resources:
112
+ requests:
113
+ memory: "256Mi"
114
+ cpu: "250m"
115
+ limits:
116
+ memory: "512Mi"
117
+ cpu: "500m"
118
+
119
+ # MCP Proxy Sidecar - bridges stdio to HTTP
120
+ - name: mcp-proxy
121
+ image: ghcr.io/sparfenyuk/mcp-proxy:latest
122
+ ports:
123
+ - containerPort: 8080
124
+ name: http
125
+ command:
126
+ - mcp-proxy
127
+ - stdio-to-sse
128
+ - http://0.0.0.0:8080
129
+ - --allow-origin=*
130
+ - --command
131
+ - node
132
+ - --args
133
+ - src/index.js
134
+ resources:
135
+ requests:
136
+ memory: "128Mi"
137
+ cpu: "100m"
138
+ limits:
139
+ memory: "256Mi"
140
+ cpu: "200m"
141
+ ---
142
+ apiVersion: v1
143
+ kind: Service
144
+ metadata:
145
+ name: ${{ env.DEPLOYMENT_NAME }}-service
146
+ spec:
147
+ selector:
148
+ app: ${{ env.DEPLOYMENT_NAME }}
149
+ ports:
150
+ - name: http
151
+ port: 80
152
+ targetPort: 8080
153
+ type: LoadBalancer
154
+ EOF
155
+
156
+
157
+ # Deploy to GKE
158
+ - name : Deploy
159
+ run : |-
160
+ kubectl apply -f k8s-manifest.yaml
161
+ kubectl rollout status deployment/${{ env.DEPLOYMENT_NAME }}
162
+ kubectl get services -o wide
0 commit comments