Skip to content

Commit 4ab0f86

Browse files
[feat] Add Docker support with GHCR publishing
- Add Dockerfile for multi-arch Docker image support (amd64/arm64) - Create GitHub Actions workflow to publish images to GHCR on releases - Add docker-test workflow for CI validation - Simplify Docker documentation to use published GHCR images - Remove .dockerignore (no longer needed with npm install approach) Docker images will be automatically published to ghcr.io/gleanwork/local-mcp-server when releases are created, providing users with a sandboxed execution environment that abstracts over local environment differences.
1 parent d4507ee commit 4ab0f86

6 files changed

Lines changed: 177 additions & 0 deletions

File tree

.env.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Glean instance name (required)
2+
GLEAN_INSTANCE=your-instance-name
3+
4+
# Glean API token (required)
5+
GLEAN_API_TOKEN=your-api-token

.github/workflows/docker-test.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: Docker Test
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
jobs:
9+
test:
10+
name: Build and Test Docker Image
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout repository
14+
uses: actions/checkout@v4
15+
16+
- name: Build Docker image
17+
run: docker build -t glean-mcp-server:test .
18+
19+
- name: Test image structure
20+
run: |
21+
docker run --rm glean-mcp-server:test node --version
22+
docker run --rm glean-mcp-server:test which npx
23+
24+
- name: Verify MCP server starts with stdio
25+
run: |
26+
container_id=$(docker run -d -i glean-mcp-server:test)
27+
sleep 2
28+
if docker ps | grep -q "$container_id"; then
29+
echo "Container is running"
30+
docker logs "$container_id"
31+
docker stop "$container_id"
32+
else
33+
echo "Container failed to start"
34+
docker logs "$container_id" || true
35+
exit 1
36+
fi
37+
38+
- name: Test with security constraints
39+
run: |
40+
container_id=$(docker run -d -i \
41+
--cpus="1.0" \
42+
--memory="2g" \
43+
--read-only \
44+
--tmpfs /tmp \
45+
--cap-drop=ALL \
46+
--security-opt=no-new-privileges:true \
47+
glean-mcp-server:test)
48+
sleep 2
49+
if docker ps | grep -q "$container_id"; then
50+
echo "Container is running with security constraints"
51+
docker logs "$container_id"
52+
docker stop "$container_id"
53+
else
54+
echo "Container failed to start with security constraints"
55+
docker logs "$container_id" || true
56+
exit 1
57+
fi
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Publish Docker Image
2+
3+
on:
4+
release:
5+
types: [published]
6+
workflow_dispatch:
7+
8+
jobs:
9+
publish:
10+
name: Build and Publish Multi-Arch Docker Image
11+
runs-on: ubuntu-latest
12+
permissions:
13+
contents: read
14+
packages: write
15+
steps:
16+
- name: Checkout repository
17+
uses: actions/checkout@v4
18+
19+
- name: Set up QEMU
20+
uses: docker/setup-qemu-action@v3
21+
22+
- name: Set up Docker Buildx
23+
uses: docker/setup-buildx-action@v3
24+
25+
- name: Log in to GitHub Container Registry
26+
uses: docker/login-action@v3
27+
with:
28+
registry: ghcr.io
29+
username: ${{ github.actor }}
30+
password: ${{ secrets.GITHUB_TOKEN }}
31+
32+
- name: Extract metadata
33+
id: meta
34+
uses: docker/metadata-action@v5
35+
with:
36+
images: ghcr.io/gleanwork/local-mcp-server
37+
tags: |
38+
type=semver,pattern={{version}}
39+
type=semver,pattern={{major}}.{{minor}}
40+
type=raw,value=latest
41+
42+
- name: Build and push multi-architecture image
43+
uses: docker/build-push-action@v5
44+
with:
45+
context: .
46+
platforms: linux/amd64,linux/arm64
47+
push: true
48+
tags: ${{ steps.meta.outputs.tags }}
49+
labels: ${{ steps.meta.outputs.labels }}
50+
cache-from: type=gha
51+
cache-to: type=gha,mode=max

Dockerfile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Use Alpine-based Node.js 20 for minimal image size and security
2+
FROM node:20-alpine
3+
4+
# Create non-root user for security best practices
5+
# uid/gid 1001 is a common convention for application users
6+
RUN addgroup -g 1001 -S nodejs && \
7+
adduser -S mcpserver -u 1001
8+
9+
# Switch to non-root user before installing packages
10+
# This ensures npm global installs go to user space, not /usr/local
11+
USER mcpserver
12+
13+
# Install the published @gleanwork/local-mcp-server package from npm
14+
# Using -g installs it globally in the user's home directory
15+
RUN npm install -g @gleanwork/local-mcp-server
16+
17+
# Run the MCP server
18+
# The server uses stdio transport and keeps running until terminated
19+
CMD ["local-mcp-server"]

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ This monorepo contains packages for Glean's local MCP server. For more details s
1010
- [@gleanwork/configure-mcp-server](https://github.com/gleanwork/configure-mcp-server) for configuring the local MCP server with popular MCP clients.
1111
- [@gleanwork/local-mcp-server](https://github.com/gleanwork/mcp-server/tree/main/packages/local-mcp-server) on running the local MCP server.
1212

13+
The local MCP server can be run via npx or Docker. See the [@gleanwork/local-mcp-server README](https://github.com/gleanwork/mcp-server/tree/main/packages/local-mcp-server#docker-deployment) for Docker deployment instructions.
14+
1315
## Contributing
1416

1517
Please see [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.

packages/local-mcp-server/README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,49 @@ To manually configure an MCP client (such as Claude Desktop, Windsurf, Cursor, e
7070

7171
Replace the environment variable values with your actual Glean credentials.
7272

73+
## Docker Deployment
74+
75+
As an alternative to npx, you can run the Glean MCP server in a Docker container. This provides isolation and consistent runtime environments.
76+
77+
Multi-architecture Docker images are published to GitHub Container Registry and work on both Intel/AMD (amd64) and Apple Silicon (arm64) systems.
78+
79+
### Pull the Image
80+
81+
```bash
82+
docker pull ghcr.io/gleanwork/local-mcp-server:latest
83+
```
84+
85+
### MCP Client Configuration
86+
87+
Configure your MCP client to use the Docker image:
88+
89+
```json
90+
{
91+
"mcpServers": {
92+
"glean": {
93+
"command": "docker",
94+
"args": [
95+
"run",
96+
"-i",
97+
"--rm",
98+
"ghcr.io/gleanwork/local-mcp-server:latest"
99+
],
100+
"env": {
101+
"GLEAN_INSTANCE": "your-instance",
102+
"GLEAN_API_TOKEN": "your-token"
103+
}
104+
}
105+
}
106+
}
107+
```
108+
109+
**Important:** The `-i` flag is required for stdio transport communication.
110+
111+
### Environment Variables
112+
113+
- `GLEAN_INSTANCE` (required): Your Glean instance name
114+
- `GLEAN_API_TOKEN` (required): Your Glean API token
115+
73116
### Debugging
74117

75118
Since MCP servers communicate over stdio, debugging can be challenging. We recommend using the [MCP Inspector](https://github.com/modelcontextprotocol/inspector), which is available as a package script:

0 commit comments

Comments
 (0)