Skip to content

Commit 0144622

Browse files
committed
Merge remote-tracking branch 'origin/main' into enable-disable-tools
2 parents 63f51fd + e08a3be commit 0144622

File tree

223 files changed

+18579
-3120
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

223 files changed

+18579
-3120
lines changed

.dockerignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@
44
!/go.mod
55
!/go.sum
66
!/.golangci.yml
7-
!/vendor
7+
!/vendor
8+
!/docs
9+
!/.git

.github/workflows/validate.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: validate
2+
3+
permissions:
4+
contents: read
5+
6+
concurrency:
7+
group: ${{ github.workflow }}-${{ github.ref }}
8+
cancel-in-progress: true
9+
10+
on:
11+
workflow_dispatch:
12+
push:
13+
branches:
14+
- 'main'
15+
tags:
16+
- 'v*'
17+
pull_request:
18+
19+
jobs:
20+
prepare:
21+
runs-on: ubuntu-24.04
22+
outputs:
23+
targets: ${{ steps.generate.outputs.targets }}
24+
steps:
25+
-
26+
name: Checkout
27+
uses: actions/checkout@v4
28+
-
29+
name: List targets
30+
id: generate
31+
uses: docker/bake-action/subaction/list-targets@v6
32+
with:
33+
target: validate-docs
34+
35+
validate:
36+
runs-on: ubuntu-24.04
37+
needs:
38+
- prepare
39+
strategy:
40+
fail-fast: false
41+
matrix:
42+
target: ${{ fromJson(needs.prepare.outputs.targets) }}
43+
steps:
44+
-
45+
name: Set up Docker Buildx
46+
uses: docker/setup-buildx-action@v3
47+
with:
48+
buildkitd-flags: --debug
49+
-
50+
name: Validate
51+
uses: docker/bake-action@v6
52+
with:
53+
targets: ${{ matrix.target }}

Dockerfile

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,52 @@
11
#syntax=docker/dockerfile:1
22

3-
ARG GO_VERSION=1.24.4
3+
ARG GO_VERSION=1.24.5
4+
ARG DOCS_FORMATS="md,yaml"
45

56
FROM --platform=${BUILDPLATFORM} golangci/golangci-lint:v2.1.6-alpine AS lint-base
67

78
FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION}-alpine AS base
8-
RUN apk add --no-cache git
9+
RUN apk add --no-cache git rsync
910
WORKDIR /app
1011

12+
# Docs generation and validation targets
13+
FROM base AS docs-gen
14+
WORKDIR /src
15+
RUN --mount=target=. \
16+
--mount=target=/root/.cache,type=cache \
17+
go build -mod=vendor -o /out/docsgen ./docs/generator/generate.go
18+
19+
FROM base AS docs-build
20+
COPY --from=docs-gen /out/docsgen /usr/bin
21+
ENV DOCKER_CLI_PLUGIN_ORIGINAL_CLI_COMMAND="mcp"
22+
ARG DOCS_FORMATS
23+
RUN --mount=target=/context \
24+
--mount=target=.,type=tmpfs <<EOT
25+
set -e
26+
rsync -a /context/. .
27+
docsgen --formats "$DOCS_FORMATS" --source "docs/generator/reference"
28+
mkdir /out
29+
cp -r docs/generator/reference/* /out/
30+
EOT
31+
32+
FROM scratch AS docs-update
33+
COPY --from=docs-build /out /
34+
35+
FROM docs-build AS docs-validate
36+
RUN --mount=target=/context \
37+
--mount=target=.,type=tmpfs <<EOT
38+
set -e
39+
rsync -a /context/. .
40+
git add -A
41+
rm -rf docs/generator/reference/*
42+
cp -rf /out/* ./docs/generator/reference/
43+
if [ -n "$(git status --porcelain -- docs/generator/reference)" ]; then
44+
echo >&2 'ERROR: Docs result differs. Rebase on main branch and rerun "make docs"'
45+
git status --porcelain -- docs/generator/reference
46+
exit 1
47+
fi
48+
EOT
49+
1150
FROM base AS lint
1251
COPY --from=lint-base /usr/bin/golangci-lint /usr/bin/golangci-lint
1352
ARG TARGETOS
@@ -76,19 +115,19 @@ COPY --from=packager-docker-mcp /out .
76115

77116

78117
# Build the mcp-gateway image
79-
FROM golang:1.24.4-alpine3.22@sha256:68932fa6d4d4059845c8f40ad7e654e626f3ebd3706eef7846f319293ab5cb7a AS build-mcp-gateway
118+
FROM golang:${GO_VERSION}-alpine AS build-mcp-gateway
80119
WORKDIR /app
81120
RUN --mount=type=cache,target=/root/.cache/go-build,id=mcp-gateway \
82121
--mount=source=.,target=. \
83122
go build -trimpath -ldflags "-s -w" -o / ./cmd/docker-mcp/
84123

85-
FROM golang:1.24.4-alpine3.22@sha256:68932fa6d4d4059845c8f40ad7e654e626f3ebd3706eef7846f319293ab5cb7a AS build-mcp-bridge
124+
FROM golang:${GO_VERSION}-alpine AS build-mcp-bridge
86125
WORKDIR /app
87126
RUN --mount=type=cache,target=/root/.cache/go-build \
88127
--mount=source=./tools/docker-mcp-bridge,target=. \
89128
go build -trimpath -ldflags "-s -w" -o /docker-mcp-bridge .
90129

91-
FROM alpine:3.22@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be023728e11715 AS mcp-gateway
130+
FROM alpine:3.22@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1 AS mcp-gateway
92131
RUN apk add --no-cache docker-cli socat jq
93132
VOLUME /misc
94133
COPY --from=build-mcp-bridge /docker-mcp-bridge /misc/

Makefile

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ docker-mcp-cross:
3434
docker-mcp-%:
3535
docker buildx build $(DOCKER_BUILD_ARGS) --target=package-docker-mcp --platform=$*/amd64,$*/arm64 -o ./dist .
3636

37+
docs:
38+
$(eval $@_TMP_OUT := $(shell mktemp -d -t mcp-cli-output.XXXXXXXXXX))
39+
docker buildx bake --set "*.output=type=local,dest=$($@_TMP_OUT)" update-docs
40+
rm -rf ./docs/generator/reference/*
41+
cp -R "$($@_TMP_OUT)"/* ./docs/generator/reference/
42+
rm -rf "$($@_TMP_OUT)"/*
43+
3744
push-module-image:
3845
cp -r dist ./module-image
3946
docker buildx build --push --platform=linux/amd64,linux/arm64,darwin/amd64,darwin/arm64,windows/amd64,windows/arm64 --build-arg TAG=$(TAG) --tag=docker/docker-mcp-cli-desktop-module:$(TAG) ./module-image
@@ -70,4 +77,4 @@ push-l7proxy-image:
7077
push-dns-forwarder-image:
7178
docker buildx bake dns-forwarder --push
7279

73-
.PHONY: format lint clean docker-mcp-cross push-module-image mcp-package test docker-mcp push-mcp-gateway push-l4proxy-image push-l7proxy-image push-dns-forwarder-image
80+
.PHONY: format lint clean docker-mcp-cross push-module-image mcp-package test docker-mcp push-mcp-gateway push-l4proxy-image push-l7proxy-image push-dns-forwarder-image docs

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ The MCP cli will already be installed on recent versions of Docker Desktop but y
5151
```bash
5252
# Clone the repository
5353
git clone https://github.com/docker/mcp-gateway.git
54-
cd docker-gateway
54+
cd mcp-gateway
55+
mkdir -p "$HOME/.docker/cli-plugins/"
5556

5657
# Build and install the plugin
5758
make docker-mcp

cmd/docker-mcp/client/config.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,47 @@ system:
4444
list: '.mcpServers | to_entries | map(.value + {"name": .key})'
4545
set: .mcpServers[$NAME] = $JSON
4646
del: del(.mcpServers[$NAME])
47+
gemini:
48+
displayName: Gemini CLI
49+
source: https://github.com/google-gemini/gemini-cli
50+
icon: https://avatars.githubusercontent.com/u/161781182?s=120&v=4
51+
installCheckPaths:
52+
- $HOME/.gemini
53+
- $USERPROFILE\.gemini
54+
paths:
55+
linux: $HOME/.gemini/settings.json
56+
darwin: $HOME/.gemini/settings.json
57+
windows: $USERPROFILE\.gemini\settings.json
58+
yq:
59+
list: '.mcpServers | to_entries | map(.value + {"name": .key})'
60+
set: .mcpServers[$NAME] = $JSON
61+
del: del(.mcpServers[$NAME])
62+
goose:
63+
displayName: Goose
64+
source: https://github.com/block/goose
65+
icon: https://raw.githubusercontent.com/docker/mcp-gateway/main/img/client/goose.png
66+
installCheckPaths:
67+
- $HOME/.config/goose
68+
- $USERPROFILE\.config\goose
69+
paths:
70+
linux: $HOME/.config/goose/config.yaml
71+
darwin: $HOME/.config/goose/config.yaml
72+
windows: $USERPROFILE\.config\goose\config.yaml
73+
yq:
74+
list: '.extensions | to_entries | map(select(.value.bundled != true)) | map(.value + {"name": .key})'
75+
set: '.extensions[$SIMPLE_NAME] = {
76+
"args": $JSON.args,
77+
"bundled": null,
78+
"cmd": $JSON.command,
79+
"description": "The Docker MCP Toolkit allows for easy configuration and consumption of MCP servers from the Docker MCP Catalog",
80+
"enabled": true,
81+
"env_keys": [],
82+
"envs": {},
83+
"name": $SIMPLE_NAME,
84+
"timeout": 300,
85+
"type": "stdio"
86+
}'
87+
del: del(.extensions[$SIMPLE_NAME])
4788
lmstudio:
4889
displayName: LM Studio
4990
source: https://lmstudio.ai/

cmd/docker-mcp/client/global.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ func (c *GlobalCfgProcessor) Update(key string, server *MCPServerSTDIO) error {
121121

122122
func containsMCPDocker(in []MCPServerSTDIO) bool {
123123
for _, server := range in {
124-
if server.Name == DockerMCPCatalog {
124+
if server.Name == DockerMCPCatalog || server.Name == makeSimpleName(DockerMCPCatalog) {
125125
return true
126126
}
127127
}

cmd/docker-mcp/client/yq.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"errors"
66
"os"
77
"path/filepath"
8+
"strings"
9+
"unicode"
810

911
"github.com/mikefarah/yq/v4/pkg/yqlib"
1012

@@ -62,6 +64,8 @@ func expandDelQuery(name string, key string) string {
6264
switch name {
6365
case "NAME":
6466
return stringEscape(key)
67+
case "SIMPLE_NAME":
68+
return stringEscape(makeSimpleName(key))
6569
default:
6670
return ""
6771
}
@@ -92,6 +96,8 @@ func expandSetQuery(name string, server MCPServerSTDIO) string {
9296
switch name {
9397
case "NAME":
9498
return stringEscape(server.Name)
99+
case "SIMPLE_NAME":
100+
return stringEscape(makeSimpleName(server.Name))
95101
case "JSON":
96102
result, err := json.Marshal(temp)
97103
if err != nil {
@@ -102,3 +108,13 @@ func expandSetQuery(name string, server MCPServerSTDIO) string {
102108
return ""
103109
}
104110
}
111+
112+
func makeSimpleName(name string) string {
113+
var b strings.Builder
114+
for _, r := range name {
115+
if unicode.IsLetter(r) {
116+
b.WriteRune(unicode.ToLower(r))
117+
}
118+
}
119+
return b.String()
120+
}

cmd/docker-mcp/commands/client.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func connectClientCommand(cwd string, cfg client.Config) *cobra.Command {
5151
}
5252
cmd := &cobra.Command{
5353
Use: fmt.Sprintf("connect [OPTIONS] <mcp-client>\n\nSupported clients: %s", strings.Join(client.GetSupportedMCPClients(cfg), " ")),
54-
Short: "Connect the Docker MCP Toolkit to a client",
54+
Short: fmt.Sprintf("Connect the Docker MCP Toolkit to a client. Supported clients: %s", strings.Join(client.GetSupportedMCPClients(cfg), " ")),
5555
Args: cobra.ExactArgs(1),
5656
RunE: func(cmd *cobra.Command, args []string) error {
5757
return client.Connect(cmd.Context(), cwd, cfg, args[0], opts.Global, opts.Quiet)
@@ -70,7 +70,7 @@ func disconnectClientCommand(cwd string, cfg client.Config) *cobra.Command {
7070
}
7171
cmd := &cobra.Command{
7272
Use: fmt.Sprintf("disconnect [OPTIONS] <mcp-client>\n\nSupported clients: %s", strings.Join(client.GetSupportedMCPClients(cfg), " ")),
73-
Short: "Disconnect the Docker MCP Toolkit from a client",
73+
Short: fmt.Sprintf("Disconnect the Docker MCP Toolkit from a client. Supported clients: %s", strings.Join(client.GetSupportedMCPClients(cfg), " ")),
7474
Args: cobra.ExactArgs(1),
7575
RunE: func(cmd *cobra.Command, args []string) error {
7676
return client.Disconnect(cmd.Context(), cwd, cfg, args[0], opts.Global, opts.Quiet)
@@ -84,8 +84,9 @@ func disconnectClientCommand(cwd string, cfg client.Config) *cobra.Command {
8484

8585
func manualClientCommand() *cobra.Command {
8686
cmd := &cobra.Command{
87-
Use: "manual-instructions",
88-
Args: cobra.NoArgs,
87+
Use: "manual-instructions",
88+
Short: "Display the manual instructions to connect the MCP client",
89+
Args: cobra.NoArgs,
8990
RunE: func(cmd *cobra.Command, _ []string) error {
9091
printAsJSON, err := cmd.Flags().GetBool("json")
9192
if err != nil {

0 commit comments

Comments
 (0)