mcp-gateway Documentation

Docker mcp CLI plugin / MCP Gateway

1,613 stars Go Go 76 files ยท ~56,362 tokens
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy mcp-gateway on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name mcp-gateway --restart always docker/mcp-gateway:latest

Technical Documentation: docker/mcp-gateway

โ„น๏ธ Provenance: Multi-Tier Ingestion ยท CodeWiki Reference

Overview (README.md)

Docker MCP Plugin and Docker MCP Gateway

The MCP Toolkit, in Docker Desktop, allows
developers to configure and consume MCP servers from the Docker MCP Catalog.

Underneath, the Toolkit is powered by a docker CLI plugin: docker-mcp. This repository is the code of this CLI plugin. It can work in Docker Desktop or independently.

The main feature of this CLI is the Docker MCP Gateway which allows easy and secure running and deployment of MCP servers. See Features for a list of all the features.

What is MCP?

The Model Context Protocol (MCP) is an open protocol that standardizes how AI applications connect to external data sources and tools. It provides a secure, controlled way for language models to access and interact with various services, databases, and APIs.

Overview

Developers face criticial barriers when integrating Model Context Protocol (MCP) tools into production workflows:

  • Managing MCP server lifecycle Each local MCP sever in the catalog runs in an isolated Docker container. npx and uvx servers are granted minimal host privileges.
  • Providing a unified interface AI models access MCP servers through a single Gateway.
  • Handling authentication and security Keep secrets out of environment variables using Docker Desktop's secrets management.
  • Supports dynamic tool discovery and configuration. Each MCP client (eg VS Code, Cursor, Claude Desktop, etc.) connects to the same Gateway configuration, ensuring consistency across different clients.
  • Enables OAuth flows for MCPs that require OAuth access token service connections.

Features

  • ๐Ÿณ Container-based Servers: Run MCP servers as Docker containers with proper isolation.
  • ๐Ÿ”ง Server Management: List, inspect, and call MCP tools, resources and prompts from multiple servers.
  • ๐Ÿ” Secrets Management: Secure handling of API keys and credentials via Docker Desktop.
  • ๐ŸŒ OAuth Integration: Built-in OAuth flows for service authentication.
  • ๐Ÿ“‹ Server Catalog: Manage and configure multiple MCP catalogs.
  • ๐Ÿ” Dynamic Discovery: Automatic tool, prompt, and resource discovery from running servers.
  • ๐Ÿ“Š Monitoring: Built-in logging and call tracing capabilities.

Installation

Prerequisites

  • Docker Desktop 4.59+ (with MCP Toolkit feature enabled)

  • Go 1.24+ (for development)

Install as Docker CLI Plugin

The MCP cli will already be installed on recent versions of Docker Desktop but you can build and install the latest version by following these steps:

bash
# Clone the repository
git clone https://github.com/docker/mcp-gateway.git
cd mcp-gateway
mkdir -p "$HOME/.docker/cli-plugins/"

# Build and install the plugin
make docker-mcp

After installation, the plugin will be available as:

bash
docker mcp --help

Usage

[!NOTE]
Running without Docker Desktop Feature Flags

If you encounter "Docker Desktop is not running" errors when the Docker daemon is active, you can bypass Desktop feature checks by setting:

bash
export DOCKER_MCP_IN_CONTAINER=1

This is useful when running in WSL2, containerized environments, or Docker CE where Desktop backend sockets are unavailable.

[!NOTE]
Enabling Profiles outside Docker Desktop

Profiles are enabled automatically in Docker Desktop. If you are using the CLI independently (e.g. Docker CE, WSL2, or a containerized environment), enable the profiles feature first:

bash
docker mcp feature enable profiles

Profile Management

Servers are organized into profiles. A profile groups related MCP servers together and can be connected to clients, exported, and shared via OCI registries.

Servers in a profile can reference multiple sources:

  • Catalog references: catalog://mcp/docker-mcp-catalog/github
  • OCI image references: docker://my-server:latest
  • MCP Registry references: https://registry.modelcontextprotocol.io/v0/servers/
  • Local file references: file://./server.yaml
bash
# Make sure to `docker mcp catalog pull mcp/docker-mcp-catalog` first.

# Create a new profile
docker mcp profile create --name dev-tools \
  --server catalog://mcp/docker-mcp-catalog/github

# Create a profile and connect it to a client
docker mcp profile create --name dev-tools \
  --server catalog://mcp/docker-mcp-catalog/github \
  --connect cursor

# List all profiles
docker mcp profile list

# Show profile details
docker mcp profile show <profile-id>

# Remove a profile
docker mcp profile remove <profile-id>

# Export/import profiles
docker mcp profile export <profile-id> output.yaml
docker mcp profile import input.yaml

# Push/pull profiles to OCI registries
docker mcp profile push <profile-id> <oci-reference>
docker mcp profile pull <oci-reference>

Manage servers in a profile

bash
# List servers across all profiles
docker mcp profile server ls

# Filter servers by name or profile
docker mcp profile server ls --filter name=github
docker mcp profile server ls --filter profile=dev-tools

# Add servers to a profile
docker mcp profile server add dev-tools \
  --server catalog://mcp/docker-mcp-catalog/notion

# Remove servers from a profile
docker mcp profile server remove dev-tools github slack

Configure servers in a profile

bash
# Set configuration values (<server-name>.<config-key>=<value>)
docker mcp profile config <profile-id> --set github.timeout=30

# Get configuration values (<server-name>.<config-key>)
docker mcp profile config <profile-id> --get github.timeout

# Get all configuration
docker mcp profile config <profile-id> --get-all

# Delete configuration values (<server-name>.<config-key>)
docker mcp profile config <profile-id> --del github.timeout

Manage tool allowlists in a profile

bash
# Enable specific tools (dot notation: <server>.<tool>)
docker mcp profile tools <profile-id> --enable github.create_issue --enable github.list_repos

# Disable specific tools
docker mcp profile tools <profile-id> --disable github.search_code

# Enable/disable all tools for a server
docker mcp profile tools <profile-id> --enable-all github
docker mcp profile tools <profile-id> --disable-all github

Catalog Management

Manage the OCI-based catalogs available to the MCP gateway. The default catalog is the image mcp/docker-mcp-catalog.

bash
# List catalogs
docker mcp catalog ls

# Show a catalog
docker mcp catalog show <oci-reference>

# Create a catalog from server references
docker mcp catalog create myorg/catalog:latest --title "My Catalog" \
  --server catalog://mcp/docker-mcp-catalog/github \
  --server file://./my-server.yaml

# Create a catalog from an existing profile
docker mcp catalog create myorg/catalog:latest --from-profile dev-tools

# Create a catalog from the community registry
docker mcp catalog create myorg/catalog:latest \
  --from-community-registry registry.modelcontextprotocol.io

# Push/pull catalogs to OCI registries
docker mcp catalog push <oci-reference>
docker mcp catalog pull <oci-reference>

# Manage servers within a catalog
docker mcp catalog server ls <oci-reference>
docker mcp catalog server add <oci-reference> --server docker://my-server:latest
docker mcp catalog server remove <oci-reference> github
docker mcp catalog server inspect <oci-reference> <server-name>

# Remove a catalog
docker mcp catalog remove <oci-reference>

# Tag a catalog
docker mcp catalog tag <source>:<tag> <target>:<tag>

More about importing from the OSS MCP Community Registry.

MCP Gateway Operations

Start up an MCP Gateway. This can be used for one client, or to service multiple clients if using either sse or streaming transports.

bash
# Run the MCP gateway (stdio, using the default profile)
docker mcp gateway run

# Run with a specific profile
docker mcp gateway run --profile dev-tools

# Run the MCP gateway (streaming)
docker mcp gateway run --port 8080 --transport streaming

If no --profile flag is provided, the gateway uses the default profile.

Client Connection

Connect AI clients to the MCP gateway.

bash
# List client configurations
docker mcp client ls

# Connect a client to a profile
docker mcp client connect <client-name> --profile <profile-id>

# Disconnect from a client
docker mcp client disconnect <client-name>

Secrets and OAuth

Configure MCP servers that require either secrets or OAuth.

bash
# Manage secrets
docker mcp secret --help

# Handle OAuth flows
docker mcp oauth --help

# export any desktop secrets needed by either server1 or server2
#   (temporary requirement to export secrets for docker cloud runs - this command
#    will no longer be required once Docker Cloud can access secret stores)
docker mcp secret export server1 server2

Tool Management

bash
# Count available tools
docker mcp tools count

# List all available MCP tools
docker mcp tools ls

# List all available MCP tools in JSON format
docker mcp tools ls --format=json

# Inspect a specific tool
docker mcp tools inspect <tool-name>

# Call a tool with arguments
docker mcp tools call <tool-name> [arguments...]

# Enable/disable tools for a server in a profile
docker mcp profile tools <profile-id> --enable <server>.<tool>
docker mcp profile tools <profile-id> --disable <server>.<tool>

Configuration

Configuration is stored in a local database. Profiles, catalogs, and server configuration are managed through the docker mcp profile and docker mcp catalog commands. Feature flags are stored in ~/.docker/config.json.

Environment Variables

The MCP CLI respects the following environment variables for client configuration:

  • CLAUDE_CONFIG_DIR: Override the default Claude Code configuration directory (~/.claude). When set, Claude Code will use $CLAUDE_CONFIG_DIR/.claude.json instead of ~/.claude.json for its MCP server configuration. This is useful for:
    • Maintaining separate Claude Code installations for work and personal use
    • Testing configuration changes in isolation
    • Managing multiple Claude Code profiles

Example usage:

bash
# Set custom Claude Code configuration directory
export CLAUDE_CONFIG_DIR=/path/to/custom/config

# Connect MCP Gateway to Claude Code
docker mcp client connect claude-code --profile dev-tools --global

# Claude Code will now use /path/to/custom/config/.claude.json

Architecture

The Docker MCP CLI implements a gateway pattern:

text
AI Client โ†’ MCP Gateway โ†’ MCP Servers (Docker Containers)
  • AI Client: Language model or AI application
  • MCP Gateway: This CLI tool managing protocol translation and routing
  • MCP Servers: Individual MCP servers running in Docker containers

See docs/message-flow.md for detailed message flow diagrams.

Contributing

The build instructions are available in the contribution guide.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support


Database README (`docs/database/README.md`)

Docker MCP Gateway Database

Overview

The Docker MCP Gateway uses an embedded SQLite database to store configuration data, profiles (working sets), server catalogs, and migration status. The database is located at ~/.docker/mcp/mcp-toolkit.db and is automatically created and migrated when the CLI first runs.

This document covers the database architecture, migration system, concurrent access handling, and troubleshooting.

Architecture

Database Location

text
~/.docker/mcp/
โ”œโ”€โ”€ mcp-toolkit.db           # Main SQLite database
โ”œโ”€โ”€ .mcp-toolkit-migration.lock  # Migration lock file (persists after creation)

Database Schema

The database schema is managed through versioned migrations in pkg/db/migrations/

Key Components

Database Package (pkg/db/)

  • DAO interface for all database operations
  • Migration management with golang-migrate
  • Connection pooling and configuration
  • File locking for concurrent access safety

Migration System

How Migrations Work

The Docker MCP Gateway uses golang-migrate for schema versioning:

text
Application Startup
    โ†“
pkg/db/New() called
    โ†“
[Acquire File Lock] โ† Prevents concurrent migrations
    โ†“
Check current database version
    โ†“
Database version > available migrations?
    โ”œโ”€ Yes โ†’ Return error (database from newer version)
    โ””โ”€ No  โ†’ Run pending migrations sequentially
    โ†“
[Release File Lock]
    โ†“
Database ready for use

Migration Lock File

To prevent race conditions when multiple processes start simultaneously, migrations use an OS-level file lock:

  • Lock File: ~/.docker/mcp/.mcp-toolkit-migration.lock
  • Library: github.com/gofrs/flock (cross-platform)
  • Persistence: The lock file persists on disk after migrations complete (this is intentional and safe)

Migration Operations

Migrations use both SQLite locks AND file locks:

  • File lock prevents multiple processes from attempting migrations
  • SQLite locks protect individual migration transactions
  • This two-level locking ensures safety during initialization

Why File Locking Is Necessary

Migrations with golang-migrate are not run within a single transaction. There is the possibility
for a race condition if two process concurrently attempt to run the migrations.

The Problem: When multiple processes start simultaneously:

  1. All check the database state (clean)
  2. All try to run migrations at the same time
  3. Race condition occurs โ†’ "Dirty database version" error

The Solution: OS-level file locking ensures only one process runs migrations at a time. Other processes wait, then see migrations already complete.

Database Version Compatibility

Running Older Version After Newer Version

If you run an older version of the tool after having used a newer version, the database may be at a higher schema version than the older tool expects. In this case:

  • The tool detects the database is ahead of available migrations
  • An error is returned to prevent potential data corruption:
    text
    database version 8 (~/.docker/mcp/mcp-toolkit.db) is ahead of the current application version. Please upgrade to the latest version

Testing

Concurrent Migration Test

Test that file locking prevents migration race conditions:

bash
go run test_migration_race.go

This test launches 100 concurrent processes that all try to initialize the database simultaneously. With file locking, all 100 should succeed (100% success rate). Without file locking, most would fail with "Dirty database version" errors.


Telemetry README (`docs/telemetry/README.md`)

Docker MCP Gateway Telemetry

Overview

The Docker MCP Gateway now includes comprehensive OpenTelemetry (OTEL) instrumentation to provide visibility into Model Context Protocol (MCP) operations. This telemetry system tracks all interactions between AI clients and MCP servers, providing metrics and distributed tracing for debugging, monitoring, and performance analysis.

Architecture

Data Flow

The telemetry system captures data at multiple points in the MCP Gateway architecture:

text
AI Client (e.g., Claude Code)
    โ†“
[Gateway Entry Point] โ†’ Records gateway startup
    โ†“
[Interceptor Middleware] โ†’ Tracks list operations
    โ†“
[Protocol Handlers] โ†’ Records tool/prompt/resource operations
    โ†“
[MCP Servers] โ†’ Executes requested operations
    โ†“
[Response Path] โ†’ Records duration, errors, results
    โ†“
[OTEL Collector] โ†’ Aggregates and exports metrics

Key Components

  1. Telemetry Package (internal/telemetry)

    • Initializes OTEL tracer and meter from global providers
    • Defines all metrics and span creation functions
    • Provides recording functions for each operation type
  2. Interceptor Middleware (internal/interceptors)

    • Tracks list operations (tools/list, prompts/list, resources/list, resourceTemplates/list)
    • Creates spans for tracking operation flow
    • Records metrics before operations reach handlers
  3. Protocol Handlers (internal/gateway/handlers.go)

    • Instruments tool calls, prompt retrievals, and resource reads
    • Preserves server lineage in all telemetry
    • Records operation duration and errors
  4. Periodic Export (internal/gateway/run.go)

    • Exports metrics every 30 seconds for long-running gateways
    • Configurable via DOCKER_MCP_METRICS_INTERVAL environment variable
    • Ensures metrics are available without waiting for shutdown

Telemetry Coverage

Gateway Operations

Startup and Lifecycle

  • mcp.gateway.starts - Records when the gateway starts, including transport mode (stdio/sse/streaming)
  • mcp.initialize - Records when the host initializes a connection with the gateway

Discovery Operations

When the gateway connects to MCP servers, it discovers their capabilities:

  • mcp.tools.discovered - Number of tools available per server
  • mcp.prompts.discovered - Number of prompts available per server
  • mcp.resources.discovered - Number of resources available per server
  • mcp.resource_templates.discovered - Number of resource templates available per server

Tool Schema Dialects

A discovered tool schema that declares JSON Schema draft-04, draft-06 or draft-07 is
translated into 2020-12, the only dialect MCP requires clients to support:

  • mcp.tool.schema_dialects - Counter of tool schemas by what the gateway did with the
    dialect they declared. Attributes: mcp.server.origin, mcp.tool.schema_field
    (inputSchema or outputSchema) and mcp.tool.schema_outcome:
    • translated - a declared draft-04/06/07 schema was converted to 2020-12
    • relayed - a declared draft-04/06/07 schema held a construct with no faithful 2020-12
      equivalent, so it was passed through as declared
    • unsupported_dialect - the schema declared a dialect the gateway does not translate at
      all (draft-03, 2019-09, anything unrecognised). Equally rejected by a 2020-12-only
      client, and not fixable here

This counter is not a census of discovered schemas. A schema that declares no dialect is
already 2020-12 by default and is never counted, and nothing is recorded at all when the
gateway runs with --preserve-tool-schema-dialect. A flat zero across all three outcomes
therefore means no server declares any dialect.

Client Operations

List Operations

When clients query available capabilities:

  • mcp.list.tools - Client requests list of available tools
  • mcp.list.prompts - Client requests list of available prompts
  • mcp.list.resources - Client requests list of available resources
  • mcp.list.resource_templates - Client requests list of available resource templates

Protocol Operations

Tool Calls

  • mcp.tool.calls - Counter of tool invocations
  • mcp.tool.duration - Histogram of end-to-end tool call handling time, including validation and policy checks (milliseconds)
  • mcp.tool.errors - Counter of tool execution failures

Prompt Operations

  • mcp.prompt.gets - Counter of prompt retrievals
  • mcp.prompt.duration - Histogram of prompt operation time
  • mcp.prompt.errors - Counter of prompt operation failures

Resource Operations

  • mcp.resource.reads - Counter of resource reads
  • mcp.resource.duration - Histogram of resource operation time
  • mcp.resource.errors - Counter of resource operation failures

Resource Template Operations

  • mcp.resource_template.reads - Counter of resource template reads
  • mcp.resource_template.duration - Histogram of template operation time
  • mcp.resource_template.errors - Counter of template operation failures

CLI Direct Operations

When using the Docker CLI directly (not through the gateway):

  • mcp.cli.tool.calls - Tool calls made directly from CLI
  • mcp.cli.tool.duration - CLI tool execution duration
  • mcp.cli.tools.discovered - Tools discovered via CLI commands

Catalog Management

Operations for managing MCP server configurations:

  • mcp.catalog.operations - Catalog management operations (ls, add, rm, create, push, pull, remove)
  • mcp.catalog.operation.duration - Duration of catalog operations
  • mcp.catalog.servers - Gauge showing number of servers in catalogs

Profile Operations

Operations for managing working sets (profiles) of servers:

  • mcp.profile.operations - Profile operations (create, push, pull, remove)
  • mcp.profile.operation.duration - Duration of profile operations

Metric Attributes

All metrics include contextual attributes for filtering and aggregation:

Common Attributes

  • mcp.server.name - Name of the MCP server handling the operation
  • mcp.server.origin - Name of the MCP server a capability was discovered on. This is
    what discovery and listing metrics carry; mcp.server.name is used on the tool-error
    path, paired with mcp.server.type
  • mcp.server.type - Type of server (docker, stdio, sse, unknown)

Initialize Attributes

  • mcp.client.name - Name of the connecting client (e.g. claude-ai)
  • mcp.client.version - Version of the connecting client (e.g. 0.1.0)

Operation-Specific Attributes

  • mcp.tool.name - Name of the tool being called
  • mcp.prompt.name - Name of the prompt being retrieved
  • mcp.resource.uri - URI of the resource being read
  • mcp.operation.error - Error message if operation failed
  • mcp.transport.mode - Gateway transport mode (stdio, sse, streaming)

Catalog Attributes

  • mcp.catalog.operation - Type of catalog operation (ls, add, rm, create, push, pull, remove)
  • mcp.catalog.name - Name or reference of the catalog
  • mcp.catalog.success - Boolean indicating operation success

Profile Attributes

  • mcp.profile.operation - Type of profile operation (create, push, pull, remove)
  • mcp.profile.id - Profile identifier
  • mcp.profile.success - Boolean indicating operation success

Tool Schema Dialect Attributes

  • mcp.tool.schema_field - Which schema of the tool (inputSchema, outputSchema)
  • mcp.tool.schema_outcome - What the gateway did with the declared dialect
    (translated, relayed, unsupported_dialect)

Distributed Tracing

The system creates spans for tracking operation flow:

Span Hierarchy

text
gateway.run
โ”œโ”€โ”€ tools/list
โ”œโ”€โ”€ prompts/list
โ”œโ”€โ”€ resources/list
โ”œโ”€โ”€ resourceTemplates/list
โ”œโ”€โ”€ mcp.tool.call
โ”‚   โ””โ”€โ”€ [tool execution]
โ”œโ”€โ”€ mcp.prompt.get
โ”‚   โ””โ”€โ”€ [prompt retrieval]
โ”œโ”€โ”€ mcp.resource.read
โ”‚   โ””โ”€โ”€ [resource read]
โ””โ”€โ”€ mcp.resource_template.read
    โ””โ”€โ”€ [template read]

Span Attributes

Each span includes:

  • Operation name and type
  • Server information
  • Duration
  • Error details (if failed)
  • Input parameters (tool name, prompt name, resource URI)

Server Lineage Preservation

A key feature of the telemetry system is preserving the origin server for all operations. This allows you to:

  • Track which MCP servers are most utilized
  • Identify performance bottlenecks per server
  • Monitor error rates by server
  • Understand capability usage patterns

The server information is determined by analyzing the server configuration:

  • Docker containers: Identified by image name
  • SSE endpoints: Identified by URL
  • Stdio commands: Identified by command path
  • Unknown: Fallback for unrecognized configurations

Long-Running Gateway Support

The MCP Gateway operates differently from typical Docker CLI commands. While most Docker commands are short-lived (running for seconds or minutes), the docker mcp gateway run command creates a long-running process that maintains persistent connections with AI clients. These gateway processes can run for hours, days, or even weeks as long as the client (such as Claude Code) remains connected.

Docker CLI's built-in OTEL exporter is designed for short-lived commands - it collects metrics throughout the command's execution and exports them when the command completes. This approach doesn't work well for the MCP Gateway because metrics would only be visible when the gateway shuts down, potentially days or weeks after interesting events occurred.

To address this difference, the MCP Gateway implements periodic metric export:

  1. Periodic Metric Export: Metrics are exported every 30 seconds (configurable via DOCKER_MCP_METRICS_INTERVAL)
  2. Applies to All Transport Modes: Whether using stdio, SSE, or streaming transports, all gateway processes are long-lived
  3. Non-blocking Operations: Telemetry never blocks MCP operations
  4. Memory Efficiency: Metrics are aggregated efficiently to minimize overhead
  5. Graceful Shutdown: Final metric export still occurs on gateway termination

Configuration

Checking Current Configuration

View your Docker context's OTEL settings:

bash
docker context inspect | jq '.[].Metadata.otel'

Typical output for Docker Desktop:

json
{
  "OTEL_EXPORTER_OTLP_ENDPOINT": "unix:///Users/username/.docker/run/user-analytics.otlp.grpc.sock"
}

Environment Variables

  • DOCKER_MCP_TELEMETRY_DEBUG - Enable debug logging for telemetry operations
  • DOCKER_MCP_METRICS_INTERVAL - Set metric export interval (default: 30s)
  • DOCKER_CLI_OTEL_EXPORTER_OTLP_ENDPOINT - Override OTEL collector endpoint for testing
  • OTEL_EXPORTER_OTLP_ENDPOINT - OTEL collector endpoint (inherited from Docker CLI)
  • OTEL_EXPORTER_OTLP_HEADERS - Authentication headers for OTEL collector

Debug Mode

Enable debug logging to see telemetry events:

bash
export DOCKER_MCP_TELEMETRY_DEBUG=1
docker mcp gateway run --catalog catalog.yaml

Debug output appears on stderr and includes:

  • Provider initialization status
  • Tool call instrumentation events
  • Metric recording confirmations

Integration with Docker Desktop

The telemetry system integrates with Docker Desktop's existing OTEL infrastructure:

  1. Uses Docker CLI's global OTEL providers
  2. Inherits Docker Desktop's telemetry configuration
  3. Exports to the same OTEL collector as other Docker operations
  4. Appears alongside other Docker metrics in monitoring systems

Docker Desktop vs Open Source Docker

The telemetry behavior differs between Docker Desktop and open source Docker installations:

Docker Desktop:

  • The Docker context includes OTEL configuration with an endpoint (typically a Unix socket at ~/.docker/run/user-analytics.otlp.grpc.sock)
  • The Docker Desktop backend process receives and processes metrics
  • Metrics are filtered by instrumentation scope and exported to analytics services
  • Users can disable telemetry through Docker Desktop settings

Open Source Docker (without Docker Desktop):

  • The Docker context lacks OTEL configuration, causing dockerExporterOTLPEndpoint() to return an empty endpoint
  • Without an endpoint, no metric exporter is created (dockerMetricExporter() returns nil)
  • The MCP Gateway telemetry code runs but metrics are not exported anywhere
  • No external connections are made for telemetry purposes

This design ensures that telemetry only operates within the Docker Desktop environment where users have explicitly agreed to usage analytics. Open source Docker users experience no telemetry collection, maintaining complete privacy by default.

Use Cases

Performance Monitoring

  • Track response times for different MCP servers
  • Identify slow operations by percentile analysis
  • Monitor operation volume and patterns

Debugging

  • Trace failed operations through distributed spans
  • Identify error patterns by server or operation type
  • Correlate gateway operations with server behavior

Capacity Planning

  • Understand which capabilities are most used
  • Track growth in operation volume
  • Identify servers that need scaling

Security and Compliance

  • Audit tool usage patterns
  • Track access to sensitive resources
  • Monitor for unusual operation patterns

Testing Telemetry

Quick Test

Use the provided test script for complete telemetry validation:

bash
cd docs/telemetry/testing
./test-telemetry.sh --full

Manual Testing

  1. Start an OTEL Collector:

For debug output only:

bash
docker run --rm -d --name otel-debug \
  -p 4317:4317 -p 4318:4318 \
  -v $(pwd)/docs/telemetry/testing/otel-collector-config.yaml:/config.yaml \
  otel/opentelemetry-collector:latest --config=/config.yaml

For Prometheus export (port 8889):

bash
docker run --rm -d --name otel-prometheus \
  -p 4317:4317 -p 4318:4318 -p 8889:8889 \
  -v $(pwd)/docs/telemetry/testing/otel-collector-prometheus.yaml:/config.yaml \
  otel/opentelemetry-collector:latest --config=/config.yaml
  1. Run MCP Gateway with Custom Endpoint:
bash
export DOCKER_MCP_TELEMETRY_DEBUG=1
export DOCKER_CLI_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
docker mcp gateway run --catalog ~/.docker/mcp/catalogs/docker-mcp.yaml \
  --transport sse --port 3000
  1. Make Tool Calls:
    Connect an MCP client to http://localhost:3000/sse and execute tools.

  2. View Telemetry:

bash
docker logs otel-debug | grep "mcp\."

Expected Output

When telemetry is working correctly, you'll see:

Traces:

text
Span #0
    Trace ID       : 3482c4807337c24926eca041191e9d74
    Name           : mcp.tool.call
    Kind           : Client
    Status code    : Ok
Attributes:
     -> mcp.tool.name: Str(getPersonalNamespace)
     -> mcp.server.name: Str(dockerhub)
     -> mcp.server.type: Str(docker)

Metrics:

text
Metric #0
Descriptor:
     -> Name: mcp.tool.calls
     -> Description: Number of tool calls executed
NumberDataPoints #0
     -> mcp.server.name: Str(dockerhub)
     -> mcp.tool.name: Str(getPersonalNamespace)
Value: 2

Troubleshooting

No Telemetry Visible

  1. Check Provider Types:

    bash
    DOCKER_MCP_TELEMETRY_DEBUG=1 docker mcp gateway run --dry-run

    Look for: Tracer provider type: *trace.TracerProvider (not noop)

  2. Verify Endpoint Configuration:

    • Check Docker context: docker context inspect
    • Check environment: echo $DOCKER_CLI_OTEL_EXPORTER_OTLP_ENDPOINT
  3. Ensure Tool Calls Are Made:

    • Telemetry is event-driven
    • No tool calls = no telemetry
    • Use SSE mode with an MCP client to trigger calls

Debug Logging Not Appearing

  • Ensure DOCKER_MCP_TELEMETRY_DEBUG=1 is exported
  • Check stderr output (debug logs go to stderr, not stdout)
  • Verify the plugin was rebuilt after adding telemetry

Collector Connection Issues

  • Verify collector is running: docker ps | grep otel
  • Check port availability: lsof -i :4317
  • Test connectivity: telnet localhost 4317

Privacy and Security

The telemetry system is designed with privacy in mind:

  • No PII: No personally identifiable information is collected
  • No Content: Operation contents (arguments, results) are not recorded
  • Metadata Only: Only operation metadata and performance metrics
  • Local Control: All telemetry can be disabled via Docker Desktop settings

Performance Impact

The telemetry implementation is optimized for minimal overhead:

  • Target: <1% performance impact
  • Non-blocking metric recording
  • Efficient attribute handling
  • Batched metric exports
  • No synchronous network calls in operation path

Development Guidelines

Adding New Telemetry

When adding telemetry to new operations:

  1. Use Existing Providers:

    go
    tracer := otel.GetTracerProvider().Tracer("github.com/docker/mcp-gateway")
    meter := otel.GetMeterProvider().Meter("github.com/docker/mcp-gateway")
  2. Preserve Server Lineage:
    Always include server attribution in spans and metrics:

    go
    attrs := []attribute.KeyValue{
        attribute.String("mcp.server.name", serverConfig.Name),
        attribute.String("mcp.server.type", inferServerTransportType(serverConfig)),
        attribute.String("mcp.tool.name", toolName),
    }
  3. Non-Blocking Operations:
    Telemetry must never block or fail operations:

    go
    if span != nil {
        defer span.End()
    }
    // Continue even if telemetry fails
  4. Debug Support:
    Add debug logging behind the environment flag:

    go
    if os.Getenv("DOCKER_MCP_TELEMETRY_DEBUG") != "" {
        fmt.Fprintf(os.Stderr, "[MCP-TELEMETRY] Recording tool call: %s\n", toolName)
    }

Testing Changes

  1. Build the Plugin:

    bash
    make docker-mcp
  2. Run the Test Suite:

    bash
    ./docs/telemetry/testing/test-telemetry.sh --full
  3. Verify with Real Tool Calls:
    Test in SSE mode with an actual MCP client

  4. Check Both Traces and Metrics:
    Ensure both appear correctly in the collector output

Future Enhancements

While the current implementation provides comprehensive coverage, potential future enhancements include:

MCP Protocol Operations (Planned)

  • Sampling Operations: Telemetry for when MCP servers request LLM completions from the MCP host via the client
  • Prompting Operations: Metrics for when MCP servers request user input from the MCP host via the client
  • Roots Operations: Tracking of filesystem boundaries where servers are allowed to operate

Infrastructure Metrics

  • Session-level metrics and tracking
  • Connection pool metrics
  • Interceptor execution metrics
  • Advanced sampling strategies
  • Custom dashboard templates

Summary

The Docker MCP Gateway telemetry system provides complete visibility into MCP operations, from client requests through server execution. By leveraging OpenTelemetry standards and integrating with Docker Desktop's existing infrastructure, it enables effective monitoring, debugging, and optimization of AI-powered workflows using MCP servers.

The system balances comprehensive coverage with performance efficiency, ensuring that telemetry enhances rather than hinders the gateway's operation. With built-in support for long-running processes and careful preservation of server lineage, it provides the insights needed to operate MCP infrastructure effectively at scale.

References


Catalog (`docs/catalog.md`)

MCP Catalog Management

Important note: This method of catalog management is deprecated and only works if the profiles feature flag is off. Please see Profiles for more information on how to use catalogs.

Docker MCP Gateway provides comprehensive catalog management capabilities, allowing you to create, manage, and use custom MCP server catalogs alongside Docker's official catalog.

Quick Start with Bootstrap

The easiest way to get started with custom catalogs is to use the bootstrap command, which creates a starter catalog file with Docker's official server entries as examples:

bash
# Create a starter catalog with Docker Hub and Docker CLI server examples
docker mcp catalog bootstrap ./my-starter-catalog.yaml

# The file now contains properly formatted server definitions you can modify

This creates a YAML file with real server definitions that you can:

  • Modify to understand the catalog format
  • Use as a foundation for your custom servers
  • Import directly into your catalog collection
  • Use as a source for copying individual servers to other catalogs

Catalog Management Commands

Listing Catalogs

bash
# List all configured catalogs
docker mcp catalog ls

# List in JSON format
docker mcp catalog ls --format=json

Creating Catalogs

bash
# Create a new empty catalog
docker mcp catalog create my-custom-catalog

# The catalog is now ready for adding servers

Viewing Catalog Contents

bash
# Show servers in the default Docker catalog
docker mcp catalog show

# Show servers in a specific catalog
docker mcp catalog show my-custom-catalog

# Show in different formats
docker mcp catalog show docker-mcp --format json
docker mcp catalog show docker-mcp --format yaml

Adding Servers to Catalogs

bash
# Add a server from another catalog file
docker mcp catalog add my-custom-catalog server-name ./source-catalog.yaml

# Force overwrite if server already exists
docker mcp catalog add my-custom-catalog server-name ./source-catalog.yaml --force

Importing Servers from OSS MCP Community Registry

bash
# replace {id} in the url below
docker mcp catalog import my-custom-catalog --mcp-registry https://registry.modelcontextprotocol.io/v0/servers/{id}

Importing Other Catalogs

bash
# Import a catalog from a local file
docker mcp catalog import ./my-catalog.yaml

# Import from a URL
docker mcp catalog import https://example.com/catalog.yaml

# Import with an alias
docker mcp catalog import team-servers

Exporting Catalogs

bash
# Export a custom catalog to a file
docker mcp catalog export my-custom-catalog ./backup.yaml

# Note: You cannot export Docker's official catalog
docker mcp catalog export docker-mcp ./docker-backup.yaml
# Error: Cannot export the Docker MCP catalog as it is managed by Docker

Forking Catalogs

bash
# Create a copy of an existing catalog
docker mcp catalog fork docker-mcp my-custom-version

# Now you can modify my-custom-version independently

Removing Catalogs

bash
# Remove a custom catalog
docker mcp catalog rm my-custom-catalog

# Note: You cannot remove Docker's official catalog

Updating Catalogs

bash
# Update all catalogs
docker mcp catalog update

# Update a specific catalog
docker mcp catalog update my-custom-catalog

Resetting Catalogs

bash
# Remove all custom catalogs and reset to Docker defaults
docker mcp catalog reset

Catalog YAML Format

Catalogs use a specific YAML format with server definitions. Here's the structure:

Basic Structure

yaml
name: my-catalog
displayName: My Custom Catalog
registry:
  server-name:
    description: "Description of what this server does"
    title: "Server Display Name"
    type: "server"  # or "poci" for container tools
    image: "namespace/image:tag"
    # Additional server configuration...

Complete Server Example

text
/* Detailed source-code truncated for AI context efficiency. */

POCI (Container) Tool Example

yaml
registry:
  my-container-tool:
    description: "A containerized tool for file processing"
    title: "File Processor"
    type: "poci"
    tools:
      - name: "process_files"
        description: "Process files in a directory"
        parameters:
          type: "object"
          properties:
            input_path:
              type: "string"
              description: "Path to input files"
            output_path:
              type: "string"
              description: "Path for output files"
          required: ["input_path", "output_path"]
        container:
          image: "myorg/file-processor:latest"
          command:
            - "process"
            - "{{input_path}}"
            - "{{output_path}}"
          volumes:
            - "{{input_path}}:{{input_path}}"
            - "{{output_path}}:{{output_path}}"

Common Workflows

Development Workflow

bash
# 1. Create a starter catalog for reference
docker mcp catalog bootstrap ./starter-catalog.yaml

# 2. Create your own catalog
docker mcp catalog create dev-servers

# 3. Add useful servers from the starter (optional)
docker mcp catalog add dev-servers dockerhub ./starter-catalog.yaml

# 4. Create a custom server definition file
cat > my-server.yaml << EOF
registry:
  my-dev-server:
    description: "My development server"
    title: "Dev Server"
    type: "server"
    image: "myorg/dev-server:latest"
    tools:
      - name: "dev_tool"
EOF

# 5. Add your custom server
docker mcp catalog add dev-servers my-dev-server ./my-server.yaml

Importing from the OSS MCP Community Registry

bash
# 1. Create a destination catalog for your community servers
docker mcp catalog create community-catalog

# 2. import the OSS MCP community server resource
docker mcp catalog import --mcp-registry http://registry.modelcontextprotocol.io/v0/servers/71de5a2a-6cfb-4250-a196-f93080ecc860

# 3. show the imported server
docker mcp catalog show community-catalog --format=json | jq .

Team Sharing Workflow

bash
# Team lead: Create and export a team catalog
docker mcp catalog create team-servers
docker mcp catalog add team-servers shared-db ./shared-db-server.yaml
docker mcp catalog add team-servers api-helper ./api-helper-server.yaml
docker mcp catalog export team-servers ./team-catalog.yaml

# Share team-catalog.yaml with team members

# Team members: Import the shared catalog
docker mcp catalog import ./team-catalog.yaml
docker mcp gateway run

Testing New Servers

bash
# 1. Create a test catalog
docker mcp catalog create test-servers

# 2. Add your server for testing
docker mcp catalog add test-servers test-server ./test-server.yaml

# 3. Run gateway with test catalog
docker mcp gateway run

# 4. When done testing, clean up
docker mcp catalog rm test-servers

Production Deployment

bash
# 1. Create production catalog
docker mcp catalog create prod-servers

# 2. Add only production-ready servers
docker mcp catalog add prod-servers monitoring ./monitoring-server.yaml
docker mcp catalog add prod-servers logging ./logging-server.yaml

# 3. Export for backup and deployment
docker mcp catalog export prod-servers ./prod-catalog-backup.yaml

# 4. Deploy with production catalog
docker mcp gateway run

Catalog Precedence

Catalogs are loaded in this order:

  1. Docker Official Catalog (always loaded first)
  2. Configured Catalogs (user-imported catalogs)
  3. CLI-specified Catalogs (via --catalog flag)

If multiple catalogs define the same server name, the last-loaded catalog wins. This means CLI-specified catalogs take highest precedence, followed by configured catalogs, with Docker's catalog as the base.

Registry Submission

For servers you want to share with the broader community, consider submitting them to Docker's official registry:

Official Docker MCP Registry: https://github.com/docker/mcp-registry

This process makes your servers available to all Docker MCP users through the official catalog.

Troubleshooting

File Already Exists

bash
Error: file "catalog.yaml" already exists - will not overwrite

Solution: Choose a different filename or move/remove the existing file

Server Not Found

bash
Error: server "server-name" not found in catalog "source.yaml"

Solution: Check the server name spelling and verify it exists in the source catalog

Cannot Export Docker Catalog

bash
Error: cannot export the Docker MCP catalog as it is managed by Docker

Solution: This is intentional - Docker's catalog cannot be exported. Use bootstrap to get Docker server examples instead.

Container Mode Issues

If running in container mode, ensure proper volume mounts for accessing catalog files and Docker configuration.


Config Flow (`docs/config-flow.md`)

Gateway startup

mermaid
sequenceDiagram
    participant Gateway
    participant Config
    participant Configurator
    participant Server
    participant Listener

    Gateway->>Listener: Start listening immediately if not-stdio
    Gateway->>Configurator: Read
    Configurator-->>Config: hello
    Config-->>Gateway: configured
    Configurator->>Watcher: channel
    Watcher-->>Gateway: watch channel config changes
    Gateway->>Gateway: pullAndVerify(config)
    Gateway->>Gateway: reloadConfiguration(config)
    Gateway->>Server: start
    Gateway->>Listener: healthy

Reading Config

The Read method in Configurator is responsible for building an initial Configuration

  • serverNames
  • catalog.Servers (this is our catalog)
    • read from catalog.yaml files
    • read from oci artifacts
  • config map
  • tool filters
  • secret providers
    • DD
    • file

reloadConfiguration

The gateway reloadConfiguration extracts capabilities from the current configuration, and updates the Server. It starts up the server to do this.

When running servers raise change notifications, the capabilities also have to be reloaded.

Dynamic Server Add

Another place where the capabilities should be considered dynamic is with the mcp-server-add tool. This tool loads new mcp servers into a gateway session.

mermaid
sequenceDiagram
    AddTool->>Config: find
    AddTool->>Config: append server
    AddTool->>Config: update secrets
    AddTool->>Gateway: reloadConfiguration
    Gateway-->>Config: is used

During reloadConfiguration all updates to capabilities will cause change events to be sent to any clients connected to this server.

Images without Catalogs

A Docker Image can contain its own catalog description via the
io.docker.server.metadata label. When such an image is referenced
through a profile or working set (see profiles), the
label is parsed through the narrow ImportedServer schema so that only
descriptive metadata is trusted. Runtime-shaping fields and secrets are
sourced exclusively from curated catalogs or user configuration.


Mcp Gateway (`docs/mcp-gateway.md`)

Docker MCP Gateway

Running MCP Servers in Docker Containers is robust and secure.

See Why running MCP Servers in Container is more secure

How to run the MCP Gateway?

Start up an MCP Gateway. This can be used for one client, or to service multiple clients if using either sse or streaming transports.

bash
# Run the MCP gateway (stdio)
docker mcp gateway run

# Run the MCP gateway (streaming)
docker mcp gateway run --port 8080 --transport streaming

# Run with specific servers only, and select all tools from server1 and just tool2 from server2
docker mcp gateway run --servers server1,server2 --tools server1:* --tools server2:tool2

# Run a fallback secret lookup - lookup desktop secret first and the fallback to a local .env file
docker mcp gateway run --secrets=docker-desktop:./.env

# Run with verbose logging
docker mcp gateway run --verbose --log-calls

# Run in watch mode (auto-reload on config changes)
docker mcp gateway run --watch

# Run a standalone dockerized MCP server (no catalog required)
docker mcp gateway run --server docker.io/namespace/repository:latest

# Run with a profile (requires profiles feature to be enabled)
docker mcp gateway run --profile my-working-set

See Profiles for more information about organizing servers into reusable collections.

How to connect to an MCP Client?

A typical usage looks like this Claude Desktop configuration:

text
{
    "mcpServers": {
        "MCP_DOCKER": {
            "command": "docker",
            "args": ["mcp", "gateway", "run"]
        }
    }
}

How to run the MCP Gateway with Docker Compose?

The simplest way to tun the MCP Gateway with Docker Compose is with this kind of compose file:

text
services:
  gateway:
    image: docker/mcp-gateway
    command:
      - --servers=duckduckgo
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

What does it do?

How to run

console
docker compose up

More examples

See Examples

Complete set of command line flags

See the generated reference: docker mcp gateway run.

It is regenerated from the command definitions by make docs and checked in CI, so unlike
a pasted --help dump it cannot drift.

Troubleshooting

Look at our Troubleshooting Guide


Message Flow (`docs/message-flow.md`)

Message Flow

Src: official docs page

mermaid
sequenceDiagram
    participant LLM
    participant Client
    participant Server

    Note over Client,Server: Discovery
    Client->>Server: tools/list
    Server-->>Client: List of tools

    Note over Client,LLM: Tool Selection
    LLM->>Client: Select tool to use

    Note over Client,Server: Invocation
    Client->>Server: tools/call
    Server-->>Client: Tool result
    Client->>LLM: Process result

    Note over Client,Server: Updates
    Server--)Client: tools/list_changed
    Client->>Server: tools/list
    Server-->>Client: Updated tools

Docker Model

mermaid
sequenceDiagram
    participant LLM
    participant Client
    participant Server as Server (Gateway)<br/>mcp/docker
    participant ToolServer as Tool Server 1<br/>(tools runtime, potentially ephemeral)

    Note over Client,Server: Discovery
    Client->>Server: tools/list
    Server-->>ToolServer: tools/list
    ToolServer-->>Server: List of tools
    Server-->>Client: Combined list of tools

    Note over Client,LLM: Tool Selection
    LLM->>Client: Select tool to use

    Note over Client,Server: Invocation
    Client->>Server: tools/call
    Server->>ToolServer: tools/call
    ToolServer-->>Server: Tool result
    Server-->>Client: Tool result
    Client->>LLM: Process result

%%    Note over Client,Server: Updates
%%    Server--)Client: tools/list_changed
%%    Client->>Server: tools/list
%%    Server-->>Client: Updated tools

Oauth Ce Mode (`docs/oauth-ce-mode.md`)

OAuth DCR with Docker CE

Complete guide for using MCP Gateway OAuth with Docker Engine (CE Mode).

Prerequisites

1. Credential Helper Installed

MCP Gateway requires Docker credential helper configured to securely store OAuth tokens.

Download from releases:
https://github.com/docker/docker-credential-helpers/releases

2. Configure Docker to Use Credential Helper

Edit or create ~/.docker/config.json:

macOS:

json
{
  "credsStore": "osxkeychain"
}

Linux (Desktop):

json
{
  "credsStore": "secretservice"
}

Linux (Headless):

json
{
  "credsStore": "pass"
}

Windows:

json
{
  "credsStore": "wincred"
}

Verify configuration:

bash
# Helper should be in your PATH
which docker-credential-osxkeychain  # macOS
which docker-credential-secretservice  # Linux Desktop
which docker-credential-pass  # Linux Headless
where docker-credential-wincred.exe  # Windows

For detailed installation instructions, see:
https://github.com/docker/docker-credential-helpers

Configuration

Enable CE Mode

Set the environment variable to enable standalone OAuth:

bash
export DOCKER_MCP_USE_CE=true

Optional: Customize OAuth Callback Port

By default, MCP Gateway listens on localhost:5000 for OAuth callbacks.

If port 5000 is already in use, set a custom port:

bash
export MCP_GATEWAY_OAUTH_PORT=5001

Valid range: 1024-65535

Error handling:

  • If port is in use, you'll see a clear error message with solutions
  • Invalid port values (< 1024 or > 65535) fall back to default with warning

Usage

Step-by-Step: Authorizing an OAuth Server

This example uses Notion, but works with any OAuth-enabled MCP server.

Step 1: Enable the Server

bash
docker mcp server enable notion-remote

Step 2: Authorize

bash
docker mcp oauth authorize notion-remote

Oauth Flows (`docs/oauth-flows.md`)

OAuth Flows Comparison

2.2 Basic OAuth 2.1 Authorization

When authorization is required and not yet proven by the client, servers MUST respond
with HTTP 401 Unauthorized.

Clients initiate the
OAuth 2.1 IETF DRAFT
authorization flow after receiving the HTTP 401 Unauthorized.

The following demonstrates the basic OAuth 2.1 for public clients using PKCE.

mermaid
sequenceDiagram
    participant B as User-Agent (Browser)
    participant C as Client
    participant M as MCP Server

    C->>M: MCP Request
    M->>C: HTTP 401 Unauthorized
    Note over C: Generate code_verifier and code_challenge
    C->>B: Open browser with authorization URL + code_challenge
    B->>M: GET /authorize
    Note over M: User logs in and authorizes
    M->>B: Redirect to callback URL with auth code
    B->>C: Callback with authorization code
    C->>M: Token Request with code + code_verifier
    M->>C: Access Token (+ Refresh Token)
    C->>M: MCP Request with Access Token
    Note over C,M: Begin standard MCP message exchange

Official MCP OAuth diagram mapped

mermaid
sequenceDiagram
    participant A as Authorisation Server
    participant B as User-Agent (Browser)
    participant C as Client
    participant M as MCP Server
    participant R as Resource

    C->>M: MCP Request
    M->>R: Resource Request
    R-->>M: HTTP 401 Unauthorized
    M->>C: HTTP 401 Unauthorized
    Note over C: Generate code_verifier and code_challenge
    C->>B: Open browser with authorization URL + code_challenge
    B->>M: GET /authorize
    Note over M: User logs in and authorizes
    M->>B: Redirect to callback URL with auth code
    B->>C: Callback with authorization code
    C->>M: Token Request with code + code_verifier
    M->>C: Access Token (+ Refresh Token)
    C->>M: MCP Request with Access Token
    Note over C,M: Begin standard MCP message exchange

Questions

Docker MCP OAuth Model

Key points:

  • We implement the OAuth flows, nobody else has to.
  • Via a developer portal, 3rd parties can add OAuth clients (config with client_id, client_secret, redirect_uri).
  • We provide a secure and easy way to store and access secrets.

Pre-authorization (`docker mcp auth notion my-server`)

mermaid
sequenceDiagram
    participant A as Authorisation Server
    participant B as User-Agent (Browser)
    participant C as CLI
    participant P as DD Auth API<br>(handles all OAuth flows)
    participant SM as secret management API<br>(handles secret storage+access)
    participant M as MCP Server
    participant R as Resource

    C->>P: docker mcp auth notion my-server
    Note over A,P: Auth Phase (outcome: access/refresh token)<br>(can be local/local+partially hub/fully hub)
    P->>B: Open browser with authorization URL + code_challenge
    B->>A: login
    A->>B: consent
    B->>P: custom protocol callback with authorization code
    P->>A: Token Request with code + code_verifier
    A->>P: Access Token (+ Refresh Token)
    Note over P,SM: Secret Management Preparation/Setup Phase
    P->>SM: create policy 'notion'
    P->>SM: add 'my-server' to policy 'notion'
    P->>SM: set secret 'notion-access-token' with policy 'notion'
    Note over SM,R: Do MCP activity (eg requests to resources that require auth)
    M->>M: mount secret<br>x-secret:notion=/access-token/file.txt
    M->>SM: read access token from file
    SM->>M: grant access to token
    M->>R: Resource Request
    R-->>M: Data

Handling 401 Unauthorized

Note: Option 2 is the most elegant and safest solution. Neither the MCP server nor the MCP client need to know about all the details of the OAuth flow.

mermaid
sequenceDiagram
    participant C as MCP Client
    participant G as Gateway<br/>mcp/docker
    participant P as DD Auth API<br>(handles all OAuth flows)
    participant SM as secret management API<br>(handles secret storage+access)
    participant M as MCP Server
    participant R as Resource

    C->>G: MCP Request
    G->>M: MCP Request
    M->>SM: read access token from file
    SM->>M: grant access to token
    M->>R: Resource Request
    R-->>M: HTTP 401 Unauthorized
    Note over P,M: Option 1: MCP servers can trigger refresh
    M->>P: refresh
    Note over G,M: Option 2: The gateway can trigger refresh
    M->>G: HTTP 401 Unauthorized
    G->>P: refresh
    Note over C,M: Option 3: The client can trigger refresh
    G->>C: HTTP 401 Unauthorized
    C->>P: refresh
    Note over P,SM: Do refresh + propagate new access token
    P->>P: refresh<br>(if refresh token is expired, then re-authenticate)
    P->>SM: set secret 'notion-access-token'
    Note over SM,R: Do MCP activity (eg requests to resources that require auth)
    M->>SM: read access token from file
    SM->>M: grant access to token
    M->>R: Resource Request
    R-->>M: Data

Notes and observations

Docker has some advantages:

  • We are already running in the background all the time.
  • This allows us to handle secret storage and management seamlessly in the background on the user's machine instead of on our infrastructure.
  • We don't need to be an OAuth server to register dynamic clients.
    The client can use the credentials stored by DD, since we are in a trusted environment (on the user's machine).
    We just need to be a good proxy.
  • Usually clients have the problem of not being trusted.
    We also have an advantage here as we can use the Docker Desktop login to provide a secure environment for clients.

2.9.2 Flow Description

src

The third-party authorization flow comprises these steps:

  1. MCP client initiates standard OAuth flow with MCP server
  2. MCP server redirects user to third-party authorization server
  3. User authorizes with third-party server
  4. Third-party server redirects back to MCP server with authorization code
  5. MCP server exchanges code for third-party access token
  6. MCP server generates its own access token bound to the third-party session
  7. MCP server completes original OAuth flow with MCP client
mermaid
sequenceDiagram
    participant B as User-Agent (Browser)
    participant C as MCP Client
    participant M as MCP Server
    participant T as Third-Party Auth Server

    C->>M: Initial OAuth Request
    M->>B: Redirect to Third-Party /authorize
    B->>T: Authorization Request
    Note over T: User authorizes
    T->>B: Redirect to MCP Server callback
    B->>M: Authorization code
    M->>T: Exchange code for token
    T->>M: Third-party access token
    Note over M: Generate bound MCP token
    M->>B: Redirect to MCP Client callback
    B->>C: MCP authorization code
    C->>M: Exchange code for token
    M->>C: MCP access token

Questions:

  • Alano: The diagram implies that the MCP server runs remotely. Is that correct? Because why otherwise would you need the MCP client to be authorized?

All details included

mermaid
sequenceDiagram
    participant B as User-Agent (Browser)
    participant C as MCP Client
    participant M as MCP Server
    participant T as Third-Party Auth Server<br>Google, Notion, etc.

    C->>M: Initial OAuth Request
    M->>C: Auth browser URL
    C->>B: Open browser URL (Redirect to Third-Party /authorize)
    B->>T: request authorization
    T->>B: request user consent
    B->>T: user approval (consent/accept)
    T->>B: auth code in redirect URL
    B->>M: Redirect to MCP Server callback (authorization code)
    M->>T: Exchange code for token
    T->>M: access + refresh token
    M->>M: Store access + refresh token
    Note over M: Generate bound MCP token<br>MCP server becomes an auth server towards MCP client
    M->>B: Proxy auth code (redirect)
    M->>M: Store link between proxy auth code and access+refresh token
    B->>C: Proxy auth code (redirect)
    C->>M: Exchange proxy code for token
    M->>M: Link proxy access+refresh token to earlier 3rd party session
    M->>C: Proxy access+refresh token

Profiles (`docs/profiles.md`)

Profiles

Profiles allow you to organize and manage collections of MCP servers as a single unit. Unlike catalogs that serve as repositories of available servers, profiles represent specific configurations of servers you want to use together for different purposes or contexts.

What are Profiles?

A profile is a named collection of MCP servers that can be:

  • Created and managed independently of catalogs
  • Shared across teams via export/import or OCI registries
  • Used to quickly switch between different server configurations

Profiles are decoupled from catalogs, meaning the servers in a profile can come from:

  • MCP Registry references: HTTP(S) URLs pointing to servers in the Model Context Protocol registry
  • OCI image references: Docker images with the docker:// prefix
  • Catalog references: Servers from existing catalogs with the catalog:// prefix
  • Local file references: Server definitions from local YAML or JSON files with the file:// prefix (see Server Entry Specification for file format details)

โš ๏ธ Important Caveat: MCP Registry references are not fully implemented and are not expected to work yet.

Enabling Profiles

Profiles are a feature that must be enabled first.

In Docker CE or container mode:

bash
# Enable the profiles feature
docker mcp feature enable profiles

# Verify it's enabled
docker mcp feature list

If you're using Docker Desktop, you have to enable the MCPWorkingSets feature flag within Docker Desktop instead.

Once enabled, you'll have access to:

  • docker mcp profile commands for managing profiles
  • --profile flag for docker mcp gateway run
  • -p or --profile flag for docker mcp client connect

Profile Commands

Creating Profiles

Create a new profile with a name and list of servers:

bash
# Create a profile with OCI image references
docker mcp profile create --name dev-tools \
  --server docker://my-server:latest \
  --server docker://my-other-server:latest

# Create with servers from a catalog
docker mcp profile create --name catalog-servers \
  --server catalog://mcp/docker-mcp-catalog/github+slack

# Create with MCP Registry references
docker mcp profile create --name registry-servers \
  --server https://registry.modelcontextprotocol.io/v0/servers/71de5a2a-6cfb-4250-a196-f93080ecc860

# Mix different methods of specifying servers
docker mcp profile create --name mixed \
  --server catalog://mcp/docker-mcp-catalog/dockerhub \
  --server https://registry.modelcontextprotocol.io/v0/servers/71de5a2a-6cfb-4250-a196-f93080ecc860 \
  --server docker://my-server:latest
  --server file://./my-server.yaml

# Create with servers from local files
docker mcp profile create --name local-servers \
  --server file://./my-server.yaml \
  --server file://./another-server.json

# Specify a custom ID (otherwise derived from name)
docker mcp profile create --name "My Servers" --id my-servers \
  --server docker://my-server:latest

Notes:

  • --name is required and serves as the human-readable name
  • --id is optional; if not provided, it's generated from the name (lowercase, alphanumeric with underscores)
  • --server can be specified multiple times to add multiple servers
  • Server references must be either:
    • docker:// prefix for OCI images
    • http:// or https:// URLs for MCP Registry references
    • catalog:// prefix for catalog references
    • file:// prefix for local YAML or JSON server definition files

Adding Servers to a Profile

After creating a profile, you can add more servers to it:

bash
# Add servers with OCI references
docker mcp profile server add dev-tools \
  --server docker://my-server:latest \
  --server docker://my-other-server:latest

# Add servers from a catalog
docker mcp profile server add dev-tools \
  --server catalog://mcp/docker-mcp-catalog/github+slack

# Add servers with MCP Registry references
docker mcp profile server add dev-tools \
  --server https://registry.modelcontextprotocol.io/v0/servers/71de5a2a-6cfb-4250-a196-f93080ecc860

# Mix MCP Registry references and OCI references
docker mcp profile server add dev-tools \
  --server https://registry.modelcontextprotocol.io/v0/servers/71de5a2a-6cfb-4250-a196-f93080ecc860 \
  --server docker://my-server:latest

# Add servers from local files
docker mcp profile server add dev-tools \
  --server file://./my-server.yaml \
  --server file://./another-server.json

# Mix catalog servers with direct server references
docker mcp profile server add dev-tools \
  --server catalog://mcp/docker-mcp-catalog/github \
  --server docker://my-server:latest

Local File Format:

When using file://, the file should contain a server definition in YAML or JSON format:

yaml
# my-server.yaml
name: my-custom-server
title: My Custom Server
type: server
image: my-org/my-server:latest
description: A custom MCP server
allowHosts:
  - api.example.com:443

See the Server Entry Specification for complete file format documentation including configuration schemas, secrets, OAuth, and advanced options.

Server References:

  • Use --server flag for all server references (can be specified multiple times)
  • Server references must start with:
    • catalog:// for catalog references. This takes the form of catalog://<catalog-oci-refence>/<server-1>+<server-2>
    • docker:// for OCI images
    • http:// or https:// for MCP Registry URLs
    • file:// for local YAML or JSON server definition files (see Server Entry Specification)
  • Catalog servers are referenced by their name within the catalog

Notes:

  • You can add multiple servers in a single command
  • You can mix direct server references with catalog-based references
  • If a server already exists in the profile, the operation will skip it or update it

Removing Servers from a Profile

Remove servers from a profile by their server name:

bash
# Remove servers by name
docker mcp profile server remove dev-tools \
  --name github \
  --name slack

# Remove a single server
docker mcp profile server remove dev-tools --name github

# Using alias
docker mcp profile server rm dev-tools --name github

Server Names:

  • Use --name flag to specify server names to remove (can be specified multiple times)
  • Server names are determined by the server's snapshot (not the image name or source URL)
  • Use docker mcp profile show to see available server names in a profile

Listing Servers Across Profiles

View all servers grouped by profile, with filtering capabilities:

bash
# List all servers across all profiles
docker mcp profile servers

# Filter servers by name (case-insensitive substring matching)
docker mcp profile servers --filter github

# Show servers from a specific profile only
docker mcp profile servers --profile dev-tools

# Combine filter and profile
docker mcp profile servers --profile dev-tools --filter slack

# Output in JSON format
docker mcp profile servers --format json

# Output in YAML format
docker mcp profile servers --format yaml

Output options:

  • --filter: Search for servers matching a query (case-insensitive substring matching on image names or source URLs)
  • --profile or -p: Show servers only from a specific profile
  • --format: Output format - human (default), json, or yaml

Notes:

  • This command provides a global view of all servers across your profiles
  • Useful for finding which profiles contain specific servers
  • The filter applies to both image names and source URLs

Listing Profiles

View all profiles in your system:

bash
# List all profiles (human-readable format)
docker mcp profile list

# List with aliases
docker mcp profile ls

# List in JSON format
docker mcp profile list --format json

# List in YAML format
docker mcp profile list --format yaml

Output formats:

  • human (default): Tabular format with ID and Name columns
  • json: Complete JSON representation
  • yaml: Complete YAML representation

Showing Profile Details

Display detailed information about a specific profile:

bash
# Show a profile (human-readable)
docker mcp profile show my-profile

# Show in JSON format
docker mcp profile show my-profile --format json

# Show in YAML format
docker mcp profile show my-profile --format yaml

The output includes:

  • Profile ID and name
  • List of servers with their types and references
  • Configuration for each server
  • Secrets configuration
  • Tools associated with each server

Removing Profiles

Delete a profile from your system:

bash
# Remove a profile
docker mcp profile remove my-profile

# Using alias
docker mcp profile rm my-profile

Note: This only removes the profile definition, not the actual server images or registry entries.

Configuring Profile Servers

Manage configuration values for servers within a profile:

bash
# Set a single configuration value
docker mcp profile config my-profile --set github.timeout=30

# Set multiple configuration values
docker mcp profile config my-profile \
  --set github.timeout=30 \
  --set github.maxRetries=3 \
  --set slack.channel=general

# Get a specific configuration value
docker mcp profile config my-profile --get github.timeout

# Get multiple configuration values
docker mcp profile config my-profile \
  --get github.timeout \
  --get github.maxRetries

# Get all configuration values
docker mcp profile config my-profile --get-all

# Delete configuration values
docker mcp profile config my-profile --del github.maxRetries

# Combine operations (set new values and get existing ones)
docker mcp profile config my-profile \
  --set github.timeout=60 \
  --get github.maxRetries

# Output in JSON format
docker mcp profile config my-profile --get-all --format json

# Output in YAML format
docker mcp profile config my-profile --get-all --format yaml

Configuration format:

  • --set: Format is <server-name>.<config-key>=<value> (can be specified multiple times)
  • --get: Format is <server-name>.<config-key> (can be specified multiple times)
  • --del: Format is <server-name>.<config-key> (can be specified multiple times)
  • --get-all: Retrieves all configuration values from all servers in the profile
  • --format: Output format - human (default), json, or yaml

Typed values via JSON:

  • Values passed to --set are parsed as JSON when possible. This allows arrays, numbers, booleans and objects.
  • If the value is not valid JSON, it is stored as a plain string.
  • Examples:
bash
# Numbers and booleans
docker mcp profile config my-profile --set github.timeout=60 --set github.debug=true

# Strings (either raw or JSON-quoted both work)
docker mcp profile config my-profile --set slack.channel=general
docker mcp profile config my-profile --set slack.channel='"general"'

# Arrays
docker mcp profile config my-profile --set filesystem.paths='["/Users/dk/dev","/Users/dk/projects"]'

# Objects
docker mcp profile config my-profile --set build.options='{"retries":3,"cache":false}'

Important notes:

  • The server name must match the name from the server's snapshot (not the image or source URL)
  • Use docker mcp profile show --format yaml to see available server names
  • Configuration changes are persisted immediately to the profile
  • You cannot both --set and --del the same key in a single command
  • Note: Config is for non-sensitive settings. Use secrets management for API keys, tokens, and passwords.

Managing Tools for Profile Servers

Control which tools are enabled or disabled for servers in a profile:

bash
# Enable specific tools for a server
docker mcp profile tools my-profile \
  --enable github.create_issue \
  --enable github.list_repos

# Disable specific tools for a server
docker mcp profile tools my-profile \
  --disable github.create_issue \
  --disable github.search_code

# Enable and disable in one command
docker mcp profile tools my-profile \
  --enable github.create_issue \
  --disable github.search_code

# Enable all tools for a server
docker mcp profile tools my-profile --enable-all github

# Disable all tools for a server
docker mcp profile tools my-profile --disable-all github

# View all enabled tools in the profile
docker mcp profile show my-profile

Tool management format:

  • --enable: Format is <server-name>.<tool-name> (can be specified multiple times)
  • --disable: Format is <server-name>.<tool-name> (can be specified multiple times)
  • --enable-all: Format is <server-name> to enable all tools for a server (can be specified multiple times)
  • --disable-all: Format is <server-name> to disable all tools for a server (can be specified multiple times)

Important notes:

  • Tool names use dot notation: <serverName>.<toolName>
  • The server name must match the name from the server's snapshot
  • Use docker mcp profile show to see which tools are currently enabled
  • By default, all tools are enabled unless explicitly disabled
  • Changes take effect immediately and persist in the profile

Managing Secrets for Profile Servers

Secrets provide secure storage for sensitive values like API keys, tokens, and passwords. Unlike configuration values, secrets are stored securely and never displayed in plain text.

bash
# Set a secret for a server in a profile
docker mcp secret set github.pat=ghp_xxxxx

Secret format:

  • Format is <server-name>.<secret-key>=<value>
  • The server name must match the name from the server's snapshot
  • Secrets are stored in Docker Desktop's secure secret store

Current Limitation: Secrets are scoped across all servers rather than for each profile. We plan to address this.

Exporting Profiles

Export a profile to a file for backup or sharing:

bash
# Export to YAML
docker mcp profile export my-profile ./my-profile.yaml

# Export to JSON
docker mcp profile export my-profile ./my-profile.json

The file format is automatically detected from the extension (.yaml or .json).

Importing Profiles

Import a profile from a file:

bash
# Import from YAML
docker mcp profile import ./my-profile.yaml

# Import from JSON
docker mcp profile import ./my-profile.json

Behavior:

  • If a profile with the same ID doesn't exist, it will be created
  • If a profile with the same ID exists, it will be updated
  • The file format is automatically detected from the extension

Pushing Profiles to OCI Registry

Share profiles via OCI registries:

bash
# Push to a registry
docker mcp profile push my-profile docker.io/myorg/my-profile:latest

# Push to a private registry
docker mcp profile push my-profile registry.example.com/team/profile:v1.0

This allows you to:

  • Version control your profiles
  • Share with team members
  • Deploy consistent configurations across environments

Pulling Profiles from OCI Registry

Retrieve profiles from OCI registries:

bash
# Pull from a registry
docker mcp profile pull docker.io/myorg/my-profile:latest

# Pull from a private registry
docker mcp profile pull registry.example.com/team/profile:v1.0

The profile will be imported into your local system and ready to use.

Using Profiles with the Gateway

Once you have profiles configured, you can use them to run the MCP gateway:

bash
# Run gateway with a specific profile
docker mcp gateway run --profile my-profile

# The gateway will start with only the servers defined in that profile

Important restrictions:

  • --profile cannot be used with --servers flag
  • --profile cannot be used with --enable-all-servers flag
  • These flags are mutually exclusive to ensure clear server selection

Current limitations:

  • Profiles currently support image-only servers in the gateway
  • Configuration and secrets support is being expanded
  • Watch mode and dynamic updates are in development

Using Profiles with MCP Clients

Connect an MCP client with a specific profile:

bash
# Connect client with a profile
docker mcp client connect claude -p my-profile

# Using long form
docker mcp client connect cursor --profile my-profile

# Connect upon creating the profile
docker mcp profile create --name my-profile --connect cursor

This generates the appropriate client configuration using the servers from your profile.

Profile File Format

Profiles are stored in YAML or JSON with the following structure:

YAML Format

yaml
version: 1
id: my-profile
name: My Profile
servers:
  - type: image
    image: mcp/github:latest
  - type: registry
    source: https://registry.modelcontextprotocol.io/v0/servers/71de5a2a-6cfb-4250-a196-f93080ecc860
    config:
      key: value
    secrets: default
    tools:
      - tool1
      - tool2
secrets:
  default:
    provider: docker-desktop-store

JSON Format

json
{
  "version": 1,
  "id": "my-profile",
  "name": "My Profile",
  "servers": [
    {
      "type": "image",
      "image": "mcp/github:latest"
    },
    {
      "type": "registry",
      "source": "https://registry.modelcontextprotocol.io/v0/servers/71de5a2a-6cfb-4250-a196-f93080ecc860",
      "config": {
        "key": "value"
      },
      "secrets": "default",
      "tools": ["tool1", "tool2"]
    }
  ],
  "secrets": {
    "default": {
      "provider": "docker-desktop-store"
    }
  }
}

Field Descriptions

  • version: Profile format version (currently 1)
  • id: Unique identifier for the profile
  • name: Human-readable name
  • servers: Array of server definitions
    • type: Either image or registry
    • image: (For type image) Docker image reference
    • source: (For type registry) MCP Registry URL
    • config: Optional configuration key-value pairs
    • secrets: Optional reference to a secrets configuration
    • tools: Optional list of specific tools to enable from this server
  • secrets: Map of secret configurations
    • provider: Currently only docker-desktop-store is supported

Common Workflows

Development Workflow

bash
# 1. Create a development profile
docker mcp profile create --name dev \
  --server catalog://mcp/docker-mcp-catalog:latest/filesystem

# 2. Test it with the gateway
docker mcp gateway run --profile dev

# 3. Add more servers as needed
docker mcp profile server add dev \
  --server catalog://mcp/docker-mcp-catalog:latest/slack

# 4. Remove servers you don't need
docker mcp profile server remove dev --name filesystem

# 5. Disable dangerous tools in filesystem server for safety
docker mcp profile tools dev --disable filesystem.delete_file

# 6. View all servers across profiles to check your setup
docker mcp profile servers

# 7. Once satisfied, export for sharing
docker mcp profile export dev ./dev-profile.yaml

Team Collaboration

bash
# Team lead: Create and share
docker mcp profile create --name team-tools \
  --server docker://my-server:latest \
  --server docker://my-other-server:latest \
  --server docker://mcp/jira:latest

docker mcp profile push team-tools docker.io/myorg/team-tools:v1.0

# Team members: Pull and use
docker mcp profile pull docker.io/myorg/team-tools:v1.0
docker mcp gateway run --profile team-tools

Environment-Specific Configurations

bash
# Create different profiles for different environments
docker mcp profile create --name production \
  --server docker://monitoring:latest \
  --server docker://logging:latest

docker mcp profile create --name staging \
  --server docker://monitoring:latest \
  --server docker://logging:latest \
  --server docker://debug:latest

# Run with appropriate environment
docker mcp gateway run --profile production  # In production
docker mcp gateway run --profile staging     # In staging

Project-Based Organization

bash
# Create profiles per project
docker mcp profile create --name project-a \
  --server docker://my-server:latest \
  --server docker://postgres:latest

docker mcp profile create --name project-b \
  --server docker://my-server:latest \
  --server docker://mongodb:latest

# Switch between projects easily
docker mcp gateway run --profile project-a
# ... or ...
docker mcp gateway run --profile project-b

Versioning Profiles

bash
# Create a profile
docker mcp profile create --name my-tools \
  --server docker://my-server:v1.0

# Push version 1.0
docker mcp profile push my-tools docker.io/myorg/my-tools:1.0

# Update the profile (modify via export/import)
docker mcp profile export my-tools ./temp.yaml
# ... edit temp.yaml ...
docker mcp profile import ./temp.yaml

# Push version 1.1
docker mcp profile push my-tools docker.io/myorg/my-tools:1.1

# Pull specific version when needed
docker mcp profile pull docker.io/myorg/my-tools:1.0
docker mcp profile pull docker.io/myorg/my-tools:1.1

Building Profiles from Catalogs

bash
# 1. Import Docker's official catalog (or pull from OCI registry)
docker mcp catalog create docker-mcp-catalog \
  --from-legacy-catalog https://desktop.docker.com/mcp/catalog/v3/catalog.json

# Or pull a team catalog from OCI registry
docker mcp catalog pull myorg/team-catalog:latest

# 2. Create an initial profile
docker mcp profile create --name my-workflow

# 3. Add specific servers from Docker's official catalog
docker mcp profile server add my-workflow \
  --server catalog://docker-mcp-catalog/github+slack

# 4. Optionally add servers from another catalog or direct references
docker mcp profile server add my-workflow \
  --server catalog://my-org/team-catalog/custom-tool

# Or add a direct OCI reference
docker mcp profile server add my-workflow \
  --server docker://mcp/custom-tool:latest

# 5. Configure and use
docker mcp profile config my-workflow --set github.timeout=30
docker mcp gateway run --profile my-workflow

Fine-Tuning Tool Access

bash
# Create a production profile with restricted tool access
docker mcp profile create --name production \
  --server docker://my-server:latest \
  --server docker://my-other-server:latest

# Disable all tools first, then enable only what's needed
docker mcp profile tools production --disable-all github --disable-all slack

# Enable only safe, read-only tools for GitHub
docker mcp profile tools production \
  --enable github.list_repos \
  --enable github.get_file \
  --enable github.search_code

# Enable only message sending for Slack (no channel management)
docker mcp profile tools production \
  --enable slack.send_message \
  --enable slack.list_channels

# Verify the tool configuration
docker mcp profile show production --format yaml

# Use the restricted profile
docker mcp gateway run --profile production

Best Practices

Naming Conventions

  • Use descriptive names: dev-tools, production-monitoring, team-shared
  • Keep IDs short and memorable: dev, prod, team
  • Use versioning in OCI tags: v1.0, v1.1, latest

Organization Strategies

  • By Environment: Separate profiles for dev, staging, production
  • By Team: Different sets for frontend, backend, devops teams
  • By Project: One profile per major project or application
  • By Use Case: Sets for debugging, monitoring, development, etc.

Sharing and Collaboration

  • Use OCI registries for team sharing rather than file exports
  • Document your profiles in team wikis or READMEs
  • Use semantic versioning for profile tags
  • Keep a "team-shared" profile for common tools

Security Considerations

  • Always use docker mcp secret set for sensitive values (API keys, tokens, passwords)
  • Never use docker mcp profile config for secrets - it's for non-sensitive settings only
  • Secrets are stored in Docker Desktop's secure secret store
  • Use private OCI registries for proprietary server configurations
  • Review server references before importing from external sources
  • Use docker mcp profile tools to disable dangerous or unnecessary tools in production
  • Apply the principle of least privilege: enable only the tools actually needed
  • Create separate profiles for different security contexts (dev vs. production)

Troubleshooting

Profile Not Found

bash
Error: profile my-set not found

Solution: Check available profiles with docker mcp profile list

Feature Not Enabled

bash
Error: unknown command "profile" for "docker mcp"

Solution: In Docker CE or container mode, enable the feature with docker mcp feature enable profiles. In Docker Desktop, enable the MCPWorkingSets feature flag.

Invalid Server Reference

bash
Error: invalid server value: myserver

Solution: Ensure server references use either:

  • docker:// prefix for images
  • http:// or https:// for registry URLs
  • catalog:// prefix for catalog references
  • file:// prefix for local server definition files

Conflicting Flags

bash
Error: cannot use --profile with --servers flag

Solution: Choose either --profile or --servers, not both

ID Already Exists

bash
Error: profile with id my-set already exists

Solution: Either:

  • Choose a different name/ID
  • Remove the existing set first with docker mcp profile rm my-set
  • Omit the --id flag to auto-generate a unique ID

Export/Import File Format

bash
Error: unsupported file extension: .txt, must be .yaml or .json

Solution: Use .yaml or .json file extensions

Invalid Config Format

bash
Error: invalid config argument: myconfig, expected <serverName>.<configName>=<value>

Solution: Ensure config arguments follow the correct format:

  • For --set: <server-name>.<config-key>=<value> (e.g., github.timeout=30)
  • For --get: <server-name>.<config-key> (e.g., github.timeout)
  • For --del: <server-name>.<config-key> (e.g., github.timeout)

Server Not Found in Config Command

bash
Error: server github not found in profile

Solution:

  • Use docker mcp profile show to see available server names
  • Ensure you're using the server's name from its snapshot, not the image name or source URL
  • Server names are case-sensitive

Cannot Delete and Set Same Config

bash
Error: cannot both delete and set the same config value: github.timeout

Solution: Don't use --set and --del for the same key in a single command. Run them separately:

bash
# First delete
docker mcp profile config my-set --del github.timeout
# Then set (if needed)
docker mcp profile config my-set --set github.timeout=60

Server Not Found in Catalog

bash
Error: server 'nonexistent' not found in catalog

Solution:

  • Use docker mcp catalog show <catalog-name> to see available servers in the catalog
  • Check that the server name is spelled correctly (names are case-sensitive)

Cannot Remove Server

bash
Error: server 'github' not found in profile

Solution:

  • Use docker mcp profile show --format yaml to see current servers in the profile
  • Ensure you're using the correct server name in the snapshot (not the image name or source URL)
  • Server names are case-sensitive

Invalid Tool Name Format

bash
Error: invalid tool specification: github

Solution: Tool names must use dot notation with both server and tool name:

bash
# Wrong
docker mcp profile tools my-profile --enable github

# Correct
docker mcp profile tools my-profile --enable github.create_issue

Server Not Found When Managing Tools

bash
Error: server 'github' not found in profile

Solution:

  • Ensure the server with that snapshot name exists in the profile: docker mcp profile show --format yaml
  • Server names are case-sensitive and must match the snapshot name
  • Add the server first if it doesn't exist: docker mcp profile server add --server docker://my-org/my-server

Tool Not Found in Server

bash
Error: tool 'invalid_tool' not found in server 'github'

Solution:

  • Use docker mcp profile show --format yaml to see available tools for each server
  • Tool names are case-sensitive and must match exactly
  • Check the server's documentation for available tool names

Limitations and Future Enhancements

Current Limitations

  • Gateway support is limited to image-only servers
  • No automatic watch/reload when profiles are updated
  • Limited to Docker Desktop's secret store for secrets
  • No built-in conflict resolution for duplicate server names

Planned Enhancements

  • Full registry support in the gateway
  • Search and discovery features

Creating Catalogs

The catalog command allows you to create and share catalogs:

text
/* Detailed source-code truncated for AI context efficiency. */

Key points:

  • Catalogs are an immutable collection of MCP Servers
  • When creating a catalog from a profile, only the servers are included in the catalog.
  • Use catalogs to share a stable server collection across teams
  • Catalogs can be pushed to/pulled from OCI registries like Docker images
  • Output supports --format flag: human (default), json, or yaml

๐Ÿ’ก Tip: You can import Docker's official MCP catalog as a starting point:

bash
docker mcp catalog create docker-mcp-catalog \
  --from-legacy-catalog https://desktop.docker.com/mcp/catalog/v3/catalog.json

This gives you access to Docker's curated collection of MCP servers, which you can then use to build your profiles with the --server catalog://docker-mcp-catalog/<server> flag


Security (`docs/security.md`)

Docker MCP Gateway security model

Docker MCP Gateway is a security boundary between MCP clients and the MCP servers
that the gateway runs or connects to. The gateway is designed to reduce what a
malicious or compromised MCP server can read, receive, log, or route through the
host.

This document describes the default security boundaries for the Docker MCP
Gateway and how we triage vulnerability reports. A report is usually in scope
when an untrusted catalog entry, remote server, image label, or MCP server can
bypass one of the boundaries below without the user or operator explicitly
granting that access.

Trust assumptions

  • The local OS user, Docker daemon, Docker Desktop components, configured
    credential store, configured interceptors, and local Docker MCP configuration
    files are trusted. An attacker who can modify those inputs can change gateway
    behavior and is outside this boundary.
  • A catalog, profile, server entry, OCI image label, MCP registry entry, README
    URL, or remote MCP server URL may be untrusted. The gateway should treat those
    values as data and must not let them expand into broader host, network, secret,
    or routing access.
  • The code inside an enabled MCP server may be malicious. It should only receive
    the environment variables, secrets, filesystem mounts, network access, and MCP
    routing access granted by the gateway configuration and defaults.
  • Docker's MCP Catalog build-time review, dependency scanning, malware scanning,
    and publishing process are separate from this repository. Bypasses of those
    processes should be reported against the catalog or publishing system. Bypasses
    of gateway enforcement are in scope here.

Gateway boundaries

HTTP transports

The default stdio transport is local to the launching MCP client. When the
gateway is run with the sse or streaming HTTP transports, requests require a
Bearer token by default. The token is read from MCP_GATEWAY_AUTH_TOKEN when set
or generated by the gateway. --allow-unauthenticated is an explicit opt-out.

Browser requests with an Origin header are accepted only from localhost origins
(localhost, 127.0.0.1, or ::1). Requests without an Origin header remain
allowed so non-browser MCP clients can connect. The /health endpoint is not an
MCP protocol endpoint and is intentionally unauthenticated.

Catalogs, local files, and OCI metadata

Catalog paths supplied to gateway commands must resolve under
~/.docker/mcp/catalogs/. Local file:// server references are also resolved
relative to that trusted catalog directory, including symlink containment checks,
before a file is opened.

OCI image labels are treated as import metadata only. Labels may provide
descriptive server and tool metadata, but they must not inject runtime-shaping
fields such as commands, volume mounts, secrets, environment values, users, or
nested container configuration. Those fields must come from trusted catalog or
user configuration paths.

Remote URLs and untrusted fetches

Remote MCP URLs and untrusted HTTP fetches require public HTTPS destinations by
default. The gateway rejects userinfo, unsafe hostnames, loopback, private,
link-local, metadata-service, and other non-public IP ranges, and it validates
redirect destinations. Guarded direct transports also validate the resolved
destination at dial time.

DOCKER_MCP_ALLOW_INSECURE_REMOTE_URLS=1 is a development and test opt-out for
local or HTTP endpoints. Reports that depend on this opt-out are out of scope
unless they also bypass another documented boundary.

Image verification

Signature verification is enabled by default for Docker MCP images in the Docker
Hub mcp/ namespace. Those images must be referenced by digest when verification
is enabled, and they are verified before pull or run. --verify-signatures=false
is an explicit opt-out.

Third-party images outside Docker MCP's signing namespace are not verified with
Docker MCP signatures. Their trust comes from the user's catalog, profile, or
operator configuration choice.

Container execution

MCP server containers do not receive the user's host environment by default. The
gateway passes only configured environment variables, server config values, and
secrets declared for that server. Containers are started with Docker isolation,
no-new-privileges, and configured CPU and memory limits.

Host bind mounts from catalog or profile configuration are validated before they
are passed to Docker. Named and anonymous Docker volumes are allowed. Host path
binds default to read-only, must resolve under trusted roots such as temporary
directories or MCP_GATEWAY_DOCKER_BIND_ALLOWED_PATHS, and cannot target known
sensitive system or credential paths. Writable host path binds require an exact
path allowlist entry in MCP_GATEWAY_DOCKER_BIND_ALLOW_WRITABLE_PATHS.

Network egress is not globally denied by default. Servers can request
disableNetwork, allowHosts, and the gateway can run with --block-network to
enforce more restrictive network access. A server making network calls within the
granted network configuration is not, by itself, a gateway vulnerability.

Secrets and logs

Secrets are scoped to the server that declares them. Secret names are validated
before they are used with the credential resolver, and one server should not be
able to receive another server's declared secrets by guessing names or using
pattern metacharacters.

--block-secrets is enabled by default and scans tool-call arguments and text
responses for secret-like values before and after tool execution. --log-calls
is also enabled by default, but call logs record the tool name and argument shape
metadata only. Raw tool-call argument keys and values must not be logged by the
default call logger.

MCP routing and policy

The gateway rejects exposed tool names that collide with reserved gateway tools
or with tools from another enabled server. It also rejects collisions for prompt
names, resource URIs, and resource template URI templates. Dynamic registration
and reload paths must apply the same collision checks before capabilities become
available to clients.

Gateway policy decisions must apply consistently across direct tool calls,
dynamic tool execution, mcp-exec, and code-mode generated tools. A path that
invokes a denied or disabled backend tool despite policy is in scope.

Tool schema translation

A tool schema is a JSON document supplied by a backend server, so the gateway
treats it as untrusted input. Tool schemas declaring JSON Schema draft-04,
draft-06 or draft-07 are translated to 2020-12 before being advertised, which
means the gateway walks a document it previously relayed opaquely. That walk is
bounded in both depth and node count and leaves the schema untranslated when
either limit is exceeded; an unbounded walk over a crafted schema would be in
scope. Translation never widens what a schema accepts -- a construct with no
faithful 2020-12 equivalent is relayed as declared rather than reinterpreted --
and --preserve-tool-schema-dialect turns the translation off entirely.

In-scope report examples

  • An untrusted catalog, profile, image label, registry entry, or remote URL causes
    the gateway to read a host file outside the trusted catalog directory.
  • A server receives another server's secret, or a secret is sent to a remote
    server without being declared for that server.
  • A catalog-controlled volume mounts a sensitive host path, creates a writable
    host bind without an explicit writable allowlist entry, or smuggles Docker
    flags through mount values.
  • A default remote URL or redirect reaches loopback, private networks, cloud
    metadata endpoints, or other non-public destinations without the insecure URL
    opt-out.
  • An unauthenticated request reaches MCP protocol endpoints on the sse or
    streaming transports without --allow-unauthenticated.
  • A browser request with a non-localhost Origin can use MCP protocol endpoints.
  • A Docker MCP mcp/ image bypasses default signature verification or mutable tag
    rejection while verification is enabled.
  • A colliding tool, prompt, resource, or resource template shadows another server
    or a gateway capability.
  • Code-mode, dynamic tools, or mcp-exec can invoke a tool that policy denies.
  • Default call logging records raw tool-call argument keys or values.

Out-of-scope report examples

  • A user or operator explicitly enables unsafe behavior, such as
    --allow-unauthenticated, --verify-signatures=false,
    DOCKER_MCP_ALLOW_INSECURE_REMOTE_URLS=1, broad bind-mount allowlists,
    writable bind allowlists, custom interceptors, or intentionally granted
    secrets, and the reported behavior stays within that grant.
  • A malicious enabled MCP server abuses access that was intentionally granted to
    it, such as reading a mounted directory, using an assigned secret, contacting
    an allowed host, or returning malicious content to the MCP client.
  • Prompt injection, tool-description poisoning, or malicious content from a tool,
    README, remote service, or upstream API, unless it bypasses a gateway boundary
    described in this document.
  • Compromise of the local OS user, Docker daemon, Docker Desktop, host keychain,
    Docker credential helper, or local gateway binary.
  • Unauthenticated access to /health, or requests without an Origin header
    from non-browser clients.
  • Use of unsigned or malicious third-party images outside Docker MCP's signing
    namespace when the user or operator chose to run those images.
  • Resource consumption that remains within the configured CPU and memory limits.
  • Logs that include only tool names and argument shape metadata, without raw
    argument keys or values.

Server Entry Spec (`docs/server-entry-spec.md`)

MCP Server Entry Specification

This document defines the specification for MCP server entries in the Docker MCP Gateway catalog system.

Server entries can be defined for an mcp server by writing a yaml file and using it as a CLI flag for profiles or catalogs via --server file://my-server.yaml.

A note about legacy catalogs: Legacy catalogs such as .docker/mcp/catalogs/docker-mcp.yaml or https://desktop.docker.com/mcp/catalog/v3/catalog.yaml use a similar schema for servers under the registry property. However, this spec is intended for defining server configurations for MCP Profiles and OCI Catalogs. Thus, it's expected that this spec will drift from what exists in legacy catalogs.

Example Server Entry YAML

yaml
name: duckduckgo
title: DuckDuckGo
type: server
image: mcp/duckduckgo@sha256:68eb20db6109f5c312a695fc5ec3386ad15d93ffb765a0b4eb1baf4328dec14f
description: A Model Context Protocol (MCP) server that provides web search capabilities through DuckDuckGo, with additional features for content fetching and parsing.
allowHosts:
  - html.duckduckgo.com:443

Server Entry Structure

Core Fields

Field Type Required Description
name string Yes Unique identifier for the server. Used for referencing and managing the server.
type string Yes Server type. Must be one of: server, remote, or poci.
title string Yes Human-readable display name for the server.
description string Yes Brief description of the server's capabilities and purpose.
icon string No URL to an icon/logo representing the server.
readme string No URL to a README file with detailed documentation for the server.

Container Configuration (for type: "server")

Field Type Required Description
image string Yes* Docker image reference (can be SHA256 digest or tag). Required for server type.
command []string No Command-line arguments to pass to the container.
volumes []string No Volume mount specifications (format: host:container, host:container:ro, or host:container:rw).
user string No User to run the container as (e.g., 1000:1000).
longLived boolean No Whether the server should remain running (true) or start on-demand (false). Default: false.

Host Bind Mount Safety

Host path bind mounts default to read-only when no mode is specified. Explicit writable host path bind mounts, and no-mode bind mounts that should become writable, are rejected unless the resolved host source exactly matches an entry in MCP_GATEWAY_DOCKER_BIND_ALLOW_WRITABLE_PATHS. Use the OS path-list separator when setting multiple entries.

Setting MCP_GATEWAY_DOCKER_BIND_ALLOW_WRITABLE_PATHS means any catalog or profile you load can request that exact host path as writable. Scope writable entries to dedicated data directories, not source trees or broad project directories.

Remote Configuration (for type: "remote")

Field Type Required Description
remote Remote Yes* Remote server configuration. Required for remote type.
sseEndpoint string No Deprecated: Legacy SSE endpoint URL. Use remote instead.

Remote Object Structure:

Field Type Required Description
url string Yes URL endpoint for the remote MCP server.
transport_type string No Transport protocol type (e.g., sse for Server-Sent Events).
headers map[string]string No Custom HTTP headers to send with requests.

Authentication & Secrets

Field Type Required Description
secrets []Secret No API keys and secrets required by the server.
oauth OAuth No OAuth configuration for authentication flows.

Secret Object Structure:

Field Type Required Description
name string Yes Name of the secret. Must be prefixed by unique name of the server (e.g., brave.api_key).
env string Yes Environment variable name to inject the secret as (e.g., BRAVE_API_KEY).
example string Yes An example value for the key (e.g. your_api_key)

OAuth Object Structure:

Field Type Required Description
providers []OAuthProvider Yes List of OAuth providers supported.
scopes []string No OAuth scopes to request.

OAuthProvider Object Structure:

Field Type Required Description
provider string Yes OAuth provider identifier (e.g., github, google).
secret string Yes Reference to stored OAuth credentials. Must be prefixed by unique name of the server (e.g., asana.personal_access_token)
env string Yes Environment variable to inject OAuth token as.

Environment Variables

Field Type Required Description
env []Env No Static environment variables to set in the container.

Env Object Structure:

Field Type Required Description
name string Yes Environment variable name. (e.g. ASTRA_DB_API_ENDPOINT)
value string Yes Environment variable value. Can reference config fields using template syntax (e.g., {{astra-db.endpoint}}).

Network & Security

Field Type Required Description
disableNetwork boolean No If true, disables all network access for the container. Default: false.
allowHosts []string No Whitelist of hosts/domains the server is allowed to access (e.g., ["api.github.com:443", "github.com:443"]).

Tools Definition

Field Type Required Description
tools []Tool No Array of tools provided by this server. Used for discovery and documentation.

Tool Object Structure:

Field Type Required Description
name string Yes Tool identifier (unique within the server).
description string No Human-readable description of what the tool does.
arguments []ToolArgument No Tool argument definitions (only set for OCI catalogs, not legacy catalogs).
annotations ToolAnnotations No Tool annotations with hints about behavior (only set for OCI catalogs).

ToolArgument Object Structure:

Field Type Required Description
name string Yes Argument name.
type string No JSON Schema type (string, number, boolean, array, etc.).
desc string No Description of the argument.
items Items No For array types, defines the item schema.
optional boolean No Whether the argument is optional. Default: false.

ToolAnnotations Object Structure:

Field Type Required Description
title string No Human-readable title for the tool.
readOnlyHint boolean No Hint that the tool only reads data and does not modify state.
destructiveHint boolean No Hint that the tool may perform destructive operations.
idempotentHint boolean No Hint that the tool is idempotent (repeated calls have the same effect).
openWorldHint boolean No Hint that the tool interacts with external systems/world.

Configuration Schema

Field Type Required Description
config []ConfigObject No Array of configuration objects defining user-configurable settings for the server. Each config object represents a group of related settings that users must provide before using the server.

ConfigObject Structure:

The config field accepts an array of configuration objects. Each object defines a set of user-configurable parameters that can be referenced in environment variables using template syntax (e.g., {{server-name.property-name}}).

Field Type Required Description
name string Yes Unique identifier for this config object. Should match the server's unique name (e.g., couchbase, desktop-commander).
description string Yes Human-readable description explaining what these settings configure.
type string Yes Must be object. Defines this as a configuration object.
properties map[string]PropertySchema Yes Map of property names to their schema definitions. Each key is a field name that users will configure.
required []string No Array of property names that must be provided by the user.
anyOf []RequirementSet No Alternative requirement sets - user must satisfy at least one set.
oneOf []RequirementSet No Exclusive requirement sets - user must satisfy exactly one set.

PropertySchema Structure:

Defines the schema for a single configurable property:

Field Type Required Description
type string Yes JSON Schema type: string, number, boolean, array, or object.
description string No User-facing description explaining what this property configures.
items ItemsSchema No For array types, defines the schema of array elements.
properties map[string]PropertySchema No For object types, defines nested properties.
required []string No For object types, lists required nested properties.
default any No Default value if user doesn't provide one.
enum []any No Allowed values for this property.
pattern string No Regular expression pattern for string validation.
minimum number No Minimum value for numbers.
maximum number No Maximum value for numbers.

ItemsSchema Structure:

For array-type properties:

Field Type Required Description
type string Yes Type of array elements (e.g., string, number, object).

RequirementSet Structure:

For anyOf or oneOf conditional requirements:

Field Type Required Description
required []string Yes List of property names that must be provided together.

Config Examples:

Example 1: Simple String Properties

yaml
config:
  - name: couchbase
    description: "Configure the connection to Couchbase"
    type: object
    properties:
      cb_connection_string:
        type: string
        description: "Connection string for the Couchbase cluster"
      cb_username:
        type: string
        description: "Username for the Couchbase cluster with access to the bucket"
      cb_bucket_name:
        type: string
        description: "Bucket in the Couchbase cluster to use for the MCP server"
    required:
      - cb_connection_string
      - cb_username
      - cb_bucket_name

Example 2: Array Type Configuration

yaml
config:
  - name: desktop-commander
    description: "Configure filesystem access and network permissions"
    type: object
    properties:
      paths:
        type: array
        description: "List of directories that Desktop Commander can access"
        items:
          type: string
    required:
      - paths

Example 3: Nested Object Properties

yaml
config:
  - name: atlassian
    description: "The MCP server is allowed to access these paths"
    type: object
    properties:
      confluence:
        type: object
        properties:
          url:
            type: string
            description: "Confluence instance URL"
          username:
            type: string
            description: "Confluence username"
      jira:
        type: object
        properties:
          url:
            type: string
            description: "Jira instance URL"
          username:
            type: string
            description: "Jira username"
    anyOf:
      - required: [confluence]
      - required: [jira]

Referencing Config Values:

Config values can be referenced in environment variables and command arguments using template syntax:

yaml
name: astra-db
config:
  - name: astra-db
    description: "Configure Astra DB connection"
    type: object
    properties:
      endpoint:
        type: string
        description: "Astra DB API endpoint URL"
      token:
        type: string
        description: "Astra DB application token"
    required:
      - endpoint
      - token
env:
  - name: ASTRA_DB_API_ENDPOINT
    value: "{{astra-db.endpoint}}"
  - name: ASTRA_DB_APPLICATION_TOKEN
    value: "{{astra-db.token}}"

Metadata

Field Type Required Description
metadata Metadata No Additional metadata about the server (for display and categorization).

Metadata Object Structure:

Field Type Required Description
pulls integer No Number of Docker image pulls.
stars integer No Number of stars/ratings.
githubStars integer No Number of GitHub stars for the source repository.
category string No Category classification (e.g., Development, Cloud, AI).
tags []string No Tags for searchability and filtering.
license string No Software license (e.g., MIT, Apache-2.0).
owner string No Owner/maintainer identifier.

Server Types

Type: "server"

A containerized MCP server that runs as a Docker container managed by the gateway.

Required fields:

  • name
  • type: "server"
  • image

Example:

yaml
name: github-official
type: server
title: GitHub Official
description: Official GitHub MCP server for repository management
image: ghcr.io/github/github-mcp-server@sha256:a1d43076a36638ee24520fd6e83c3905ae41bc9850179081df1de2ba3a7afae0
icon: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
secrets:
  - name: github.personal_access_token
    env: GITHUB_PERSONAL_ACCESS_TOKEN
    example: <YOUR_TOKEN>
    description: You can create a GitHub personal access token [on GitHub](https://github.com/settings/personal-access-tokens/new)
allowHosts:
  - api.github.com:443
  - github.com:443
  - raw.githubusercontent.com:443

Type: "remote"

An MCP server hosted remotely and accessed via HTTP/SSE protocol.

Required fields:

  • name
  • type: "remote"
  • remote.url

Example:

yaml
name: cloudflare-docs
description: Access the latest documentation on Cloudflare products such as Workers, Pages, R2, D1, KV.
title: Cloudflare Docs
type: remote
remote:
  transport_type: sse
  url: https://docs.mcp.cloudflare.com/sse
icon: https://www.cloudflare.com/favicon.ico

Best Practices

  1. Naming: Use lowercase, hyphen-separated names (e.g., github-official, aws-core-mcp-server)
  2. Images: Prefer SHA256 digests for production, tags for development. Make sure images exist on a repository that can be accessed by those who can access the server entry (e.g. via code commit or in a private catalog)
  3. Security:
    • Use allowHosts to restrict network access
    • Use disableNetwork: true for tools that don't need network
    • Always use secrets for credentials, never hardcode in env

Troubleshooting (`docs/troubleshooting.md`)

Troubleshooting the MCP Gateway

Sometimes, you plug the MCP Gateway into your favorite MCP client and it doesn't work as expected.
What can you do to pinpoint where the problem comes from?

Debug the MCP Gateway's startup sequence

The go to command to start a fresh Gateway, plugged into Docker Desltop's Toolkit is this one:

console
docker mcp gateway run --verbose --dry-run

This will show you how the Gateway is reading the configuration, which servers are actually
enabled, which images are pulled and which MCP servers are started with which command line arguments.

It'll show you how many tools you have, in aggregate.

This is usually a good way to troubleshoot missing images, invalid server names, missing config
or secrets...

You can also focus a one given server with:

console
docker mcp gateway run --verbose --dry-run --servers=duckduckgo

Debug tool calls

Full fledge MCP clients might sometimes hide the errors they encounter while calling tools
on the MCP Gateway.

Here's a useful set of commands you can use to debug your tool calls:

console
# List the aggregate number of tools
docker mcp tools ls

# To see what's going on in the gateway while listing tools
docker mcp tools ls --verbose

# Call one of the tools
docker mcp tools call search query=Docker

# Be verbose and pass additional parameters to the Gateway
docker mcp tools call --gateway-arg="--servers=duckduckgo" --verbose search query=Docker

A client rejects every tool of one server: "unsupported dialect"

Some clients validate tool schemas with a validator configured for JSON Schema 2020-12
only, and refuse a tool whose schema declares an older dialect. The error names one tool
but applies to every tool on that server:

text
Tool 'list_bases' has an invalid outputSchema: JSON Schema declares an unsupported
dialect ("$schema": "http://json-schema.org/draft-07/schema#").

This is not a broken or stale server image, and rebuilding it will not help. MCP lets a
schema declare any dialect and requires clients to support only 2020-12, so both sides are
behaving correctly; servers built on the MCP TypeScript SDK declare draft-07 for every tool
because its zod converter defaults to that target.

The gateway translates draft-04, draft-06 and draft-07 tool schemas into 2020-12 before
advertising them, so an up to date gateway resolves this on its own. To see what a server
declared versus what clients are served, compare the two:

console
# what clients are served
docker mcp tools ls --format json | jq '.[] | {name, dialect: .inputSchema["$schema"]}'

# what the server declared, with translation turned off
docker mcp tools ls --gateway-arg="--preserve-tool-schema-dialect" --format json | jq '.[] | {name, dialect: .inputSchema["$schema"]}'

A schema the gateway cannot translate without changing what it accepts is relayed exactly
as the server declared it, and so is one declaring a dialect the gateway does not handle at
all (draft-03, 2019-09) โ€” that second case is counted separately as unsupported_dialect,
because nothing about the schema can be fixed here. The gateway reports those once per server and reason on its
stderr, which docker mcp tools ls surfaces under --verbose:

console
docker mcp tools ls --verbose 2>&1 | grep 'Relaying'
text
- mcp-gateway:   > Relaying 3 schema(s) from some-server with the dialect declared, outputSchema: schema declares unevaluatedProperties, which the declared dialect does not define and 2020-12 enforces

Those tools still work; a 2020-12-only client will still reject them, and the fix has to
happen in the server. The reasons are all cases where relabelling the dialect would change
which inputs the schema accepts, so the gateway declines to guess. The commonest is a
keyword the declared dialect does not define: const in a draft-04 schema, or
if/then/else in a draft-06 one, are inert where they were written and become live
assertions the moment the document claims 2020-12.


Feature Specs Dynamic Servers (`docs/feature-specs/dynamic_servers.md`)

Dynamic Server Management

Overview

The Dynamic Server Management feature allows users to dynamically add, remove, and configure MCP servers at runtime without restarting the gateway. This feature is enabled by the dynamic-tools feature flag and provides a set of internal management tools that can be called by AI clients.

Feature Flag

This feature is controlled by the dynamic-tools feature flag:

bash
# Enable dynamic tools feature
docker mcp feature enable dynamic-tools

# Check if enabled
docker config view | grep dynamic-tools

When enabled, the gateway adds five internal management tools to the available tool set.

Note: Dynamic tools are automatically disabled when using the --servers flag to explicitly specify which servers to run. This is because explicit server configuration indicates a manual mode where automatic server management tools are not needed.

Security boundary

The registry is the gateway's operator-enabled active set. Servers already in that set can be managed without an external policy provider. A catalog-only server can be activated or configuredโ€”individually or through a profileโ€”only when a non-noop policy provider explicitly allows its load action. The self-hosted/no-governance noop client is not treated as authorization to cross from the catalog into the active set.

Deployments that need catalog-wide dynamic activation must configure governance policy rules for the servers that may be loaded. Deployments requiring a fixed server set can pass the allowed names with --servers, which disables dynamic tools entirely.

Available Tools

1. mcp-find

Purpose: Search for MCP servers in the current catalog by name or description.

Parameters:

  • query (required): Search query to find servers by name or description (case-insensitive)
  • limit (optional): Maximum number of results to return (default: 10)

Example Usage:

json
{
  "name": "mcp-find",
  "arguments": {
    "query": "filesystem",
    "limit": 5
  }
}

Response: Returns matching servers with their details including name, description, required secrets, config schema, and long-lived status.

2. mcp-add

Purpose: Add a new MCP server to the registry and reload the configuration.

Parameters:

  • name (required): Name of the MCP server to add to the registry (must exist in catalog)

Example Usage:

json
{
  "name": "mcp-add",
  "arguments": {
    "name": "filesystem"
  }
}

Behavior:

  • Checks if the server exists in the catalog
  • Requires the server to be enabled already or explicitly allowed by an enforcing policy provider
  • Adds the server to the active server list (avoiding duplicates)
  • Fetches updated secrets for the new server
  • Reloads the gateway configuration
  • Returns success/error message

3. mcp-remove

Purpose: Remove an MCP server from the registry and reload the configuration.

Parameters:

  • name (required): Name of the MCP server to remove from the registry

Example Usage:

json
{
  "name": "mcp-remove",
  "arguments": {
    "name": "filesystem"
  }
}

Behavior:

  • Removes the server from the active server list
  • Reloads the gateway configuration
  • Returns success message

4. mcp-official-registry-import

Purpose: Import MCP servers from an official registry URL.

Parameters:

  • url (required): URL to fetch the official registry JSON from (must be HTTP/HTTPS)

Example Usage:

json
{
  "name": "mcp-official-registry-import",
  "arguments": {
    "url": "https://registry.example.com/servers.json"
  }
}

Behavior:

  • Validates the URL format
  • Fetches server definitions via HTTP GET
  • Adds imported servers to the local catalog
  • Automatically enables imported servers
  • Reloads the gateway configuration
  • Returns detailed summary of each imported server including:
    • Server name and description
    • Docker image information
    • Required secrets with configuration warnings
    • Available configuration schemas
    • Long-lived server indicators
    • Ready-to-use server list

5. mcp-config-set

Purpose: Set configuration values for MCP servers.

Parameters:

  • server (required): Name of the MCP server to configure
  • key (required): Configuration key to set
  • value (required): Configuration value to set (can be string, number, boolean, or object)

Example Usage:

json
{
  "name": "mcp-config-set",
  "arguments": {
    "server": "filesystem",
    "key": "allowed_paths",
    "value": ["/home/user/documents", "/tmp"]
  }
}

Behavior:

  • Requires the server to be enabled already or explicitly allowed by an enforcing policy provider
  • Creates or updates server configuration
  • Reloads the gateway configuration to apply changes
  • Returns success message with old/new values

Implementation Details

Secret Management

When servers are added dynamically, the system automatically:

  1. Fetches required secrets: Calls readDockerDesktopSecrets() with the updated server list
  2. Updates configuration: Replaces the existing secrets map with newly fetched secrets
  3. Handles errors gracefully: Logs warnings if secret fetching fails but continues operation

Duplicate Prevention

The mcp-add tool ensures server name uniqueness by:

  • Checking existing server names before adding
  • Only appending new servers if not already present
  • Maintaining the original order of servers

Configuration Reloading

All management tools trigger configuration reloading via reloadConfiguration():

  • Updates tool, prompt, and resource registrations
  • Refreshes capabilities with the MCP server
  • Applies new secrets and configurations
  • Maintains session state for existing connections

Use Cases

1. Development Workflow

text
AI: I need to work with files. Let me find filesystem tools.
Tool: mcp-find -> query: "filesystem"
AI: Great! I'll add the filesystem server.
Tool: mcp-add -> name: "filesystem"
AI: Now I can use file operations.

2. Importing Official Servers

text
AI: I want to use servers from the official registry.
Tool: mcp-official-registry-import -> url: "https://registry.mcp.dev/servers.json"
AI: Successfully imported 12 servers. I can now use them.

3. Server Configuration

text
AI: I need to configure the filesystem server with specific paths.
Tool: mcp-config-set -> server: "filesystem", key: "allowed_paths", value: ["/workspace"]
AI: Configuration updated. The server now has restricted access.

Security Considerations

  • Catalog validation: Only servers that exist in the catalog can be considered
  • Activation authorization: Catalog-only servers require an enforcing policy provider; a noop or missing policy cannot authorize individual, profile-based, or configuration-driven activation
  • Secret management: Secrets are fetched securely through Docker Desktop's secrets API
  • Configuration isolation: Server configurations are isolated and validated
  • URL validation: Official registry imports require valid HTTP/HTTPS URLs

Logging

The feature provides detailed logging for:

  • Server additions and removals
  • Configuration changes
  • Secret fetching operations
  • Import operations from external registries
  • Warnings for duplicate servers or failed operations

Error Handling

  • Missing servers: Returns helpful error messages when servers aren't found in catalog
  • Secret failures: Logs warnings but continues operation
  • Configuration errors: Returns detailed error messages for troubleshooting
  • Network failures: Handles HTTP errors gracefully for registry imports

Future Enhancements

Potential future improvements include:

  • Bulk server operations
  • Server dependency management
  • Configuration validation
  • Server status monitoring
  • Rollback capabilities

Feature Specs Embeddings Feature (`docs/feature-specs/embeddings-feature.md`)


marp: true theme: default paginate: true

Vector Embeddings for MCP Gateway

Semantic Search for MCP Servers and Tools


Overview

Added AI-powered semantic search capabilities to the MCP Gateway using OpenAI embeddings and SQLite vector database.

Key Features:

  • Vector similarity search for finding relevant MCP servers
  • Feature flag system for opt-in usage
  • Graceful fallback to keyword search

Components

mermaid
flowchart TD
    A["MCP Gateway"] --> B["Embeddings Client"]
    B --> C["Docker Container"]
    C --> D["vector-db MCP Server"]
    D --> E["SQLite-vec extension"]
    E --> F["~/.docker/mcp/vectors.db"]
    A --> G["OpenAI API"]
    G --> H["text-embedding-3-small"]
    style A fill:#e1f5ff
    style B fill:#fff3e0
    style D fill:#f3e5f5

Feature Flag System

bash
# Enable embeddings feature
docker mcp feature enable use-embeddings

# Set OpenAI API key
export OPENAI_API_KEY="sk-..."

Configuration:

  • Feature: use-embeddings (disabled by default)
  • Storage: ~/.docker/mcp/vectors.db
  • Model: OpenAI text-embedding-3-small (1536 dimensions)

How mcp-find Works with Embeddings

mermaid
sequenceDiagram
    participant User
    participant Gateway
    participant OpenAI
    participant VectorDB
    participant Catalog
    User->>Gateway: mcp-find "tools for github"
    alt Embeddings Enabled
        Gateway->>OpenAI: Generate embedding for query
        OpenAI-->>Gateway: [0.014, -0.018, ...]
        Gateway->>VectorDB: Search mcp-server-collection
        VectorDB-->>Gateway: Top 5 similar servers
        Gateway->>Catalog: Lookup server details
        Catalog-->>Gateway: Server metadata
    else Embeddings Disabled
        Gateway->>Catalog: Keyword search (title/description)
        Catalog-->>Gateway: Matching servers
    end
    Gateway-->>User: Server results

Implementation: VectorDBClient

go
type VectorDBClient struct {
    cmd     *exec.Cmd
    client  *mcp.Client
    session *mcp.ClientSession
}

// Connects to Docker container running vector-db
func NewVectorDBClient(ctx context.Context, dataDir string) (*VectorDBClient, error) {
    cmd := exec.CommandContext(ctx,
        "docker", "run", "-i", "--rm",
        "-v", fmt.Sprintf("%s:/data", dataDir),
        "-e", "DB_PATH=/data/vectors.db",
        "-e", "VECTOR_DIMENSION=1536",
        "jimclark106/vector-db:latest",
    )
    // ... MCP client setup with CommandTransport
}

Key Operations

go
type SearchArgs struct {
    Vector             []float64 `json:"vector"`
    CollectionName     string    `json:"collection_name,omitempty"`
    ExcludeCollections []string  `json:"exclude_collections,omitempty"`
    Limit              int       `json:"limit,omitempty"`
}

func (c *VectorDBClient) SearchVectors(
    ctx context.Context,
    vector []float64,
    options *SearchOptions,
) ([]SearchResult, error)

Collections:

  • Tool embeddings: one vector collection/server
  • mcp-server-collection: MCP server metadata

Updated Tools

mcp-find Tool

  • With Embeddings: Semantic search against mcp-server-collection
  • Without Embeddings: Traditional keyword matching
  • Returns: Server name, description, secrets, config schema

find-tools Tool

  • With Embeddings: AI-powered server recommendations
  • Without Embeddings: Error message with guidance
  • Input: Natural language task description
  • Output: Relevant servers from catalog

Code Structure

text
pkg/gateway/
โ”œโ”€โ”€ embeddings/
โ”‚   โ””โ”€โ”€ client.go          # VectorDBClient implementation
โ”œโ”€โ”€ findmcps.go            # findServersByEmbedding()
โ”œโ”€โ”€ findtools.go           # generateEmbedding() + find-tools tool
โ””โ”€โ”€ dynamic_mcps.go        # mcp-find tool + decodeArguments()

cmd/docker-mcp/commands/
โ”œโ”€โ”€ feature.go             # use-embeddings feature flag
โ””โ”€โ”€ gateway.go             # Feature check + client init

Embeddings Client Lifecycle

mermaid
stateDiagram-v2
    [*] --> Checking: Gateway starts
    Checking --> Disabled: Feature flag off
    Checking --> Disabled: No OPENAI_API_KEY
    Checking --> Initializing: Feature enabled + API key set
    Initializing --> Running: Docker container started
    Initializing --> Disabled: Init failed (logged warning)
    Running --> SearchVectors: find-tools called
    Running --> AddVector: Store embeddings
    Running --> ListCollections: Manage collections
    Running --> [*]: Gateway stops
    Disabled --> [*]: Gateway stops

mermaid
flowchart LR
    A[User Query] --> B[Generate Embedding]
    B --> C[OpenAI API]
    C --> D[1536-dim Vector]
    D --> E[Search VectorDB]
    E --> F[Top K Results]
    F --> G[Extract Server Names]
    G --> H[Lookup in Catalog]
    H --> I[Return Server Info]
    style A fill:#e3f2fd
    style D fill:#fff3e0
    style F fill:#f3e5f5
    style I fill:#e8f5e9

Benefits

โœ… Natural Language Search

  • "tools for github" โ†’ github server
  • "database queries" โ†’ sqlite server

โœ… Better Discovery

  • Semantic matching vs exact keywords
  • Handles synonyms and related concepts

โœ… Graceful Degradation

  • Falls back to keyword search if unavailable
  • Gateway continues working without embeddings

โœ… Opt-in Feature

  • Disabled by default
  • Requires explicit enablement + API key

Testing & Validation

Build:

bash
make docker-mcp
make lint

Enable Feature:

bash
docker mcp feature enable use-embeddings
export OPENAI_API_KEY="sk-..."
docker mcp gateway run

Test Search:

bash
# Via Claude Desktop or other MCP client
Find mcp tools that can help me ...

Implementation Details

Files Created:

  • pkg/gateway/embeddings/client.go (318 lines)
  • pkg/gateway/findmcps.go (83 lines)

Files Modified:

  • pkg/gateway/dynamic_mcps.go - Base64 decoding + mcp-find handler
  • pkg/gateway/findtools.go - Embedding generation
  • pkg/gateway/run.go - Client initialization
  • pkg/gateway/config.go - UseEmbeddings flag
  • cmd/docker-mcp/commands/feature.go - Feature registration
  • cmd/docker-mcp/commands/gateway.go - Feature check

Future Enhancements

๐Ÿ”ฎ Possible Improvements:

  • distribute embeddings with catalogs
  • Support other embedding models and providers
  • Automatic reindexing on catalog changes

Summary

โœจ What We Built:

  • sqlite-vec integration
  • LLM embeddings integration
  • Semantic search for MCP servers

๐ŸŽฏ Impact:

  • Better server/tool discovery
  • Natural language queries
  • Foundation for AI-powered gateway

Questions?

Documentation:

  • Feature flags: docker mcp feature ls
  • sqlite-vec service image: jimclark106/vector-db:latest
  • model: text-embedding-3-small

Storage:

  • ~/.docker/mcp/vectors.db
  • ~/.docker/config.json (feature flags)

Code:

  • Branch: slim/embeddings
  • Main files: pkg/gateway/embeddings/, findmcps.go

Feature Specs Catalog Management Feature Spec (`docs/feature-specs/catalog-management/feature-spec.md`)

User-Managed Catalogs Feature Specification

Overview

Enable Docker MCP Gateway users to create, manage, and automatically use custom MCP server catalogs alongside the default Docker catalog, while maintaining backward compatibility with Docker Desktop.

Background

Current State

  • Docker Official Catalog: Hardcoded catalog at https://desktop.docker.com/mcp/catalog/v2/catalog.yaml
  • Catalog Management System: Full CRUD operations exist but are hidden and unused by gateway runtime
  • Multi-Catalog Gateway: Infrastructure exists but defaults to Docker-only catalog
  • Docker Desktop: Expects explicit catalog requests, doesn't auto-discover user catalogs

Problem Statement

Users can create and manage custom catalogs using hidden commands (create, add, import, fork, rm), but the gateway runtime ignores these catalogs and only uses the hardcoded Docker catalog. This forces users to manually specify catalog paths via CLI flags for every gateway run.

Goals

Primary Goals

  1. Enable User-Managed Catalogs: Allow users to create custom catalogs that automatically work with the gateway
  2. Maintain Docker Desktop Compatibility: Ensure existing Docker Desktop integration remains unchanged
  3. Progressive Enhancement: Provide opt-in feature activation with safe defaults
  4. Unified User Experience: Eliminate the need for manual --catalog flags in typical usage

Secondary Goals

  1. Discoverability: Make catalog management commands visible to users
  2. Clear Precedence: Define predictable catalog merge behavior when servers conflict
  3. Comprehensive Logging: Provide visibility into catalog loading and conflicts
  4. Container Support: Ensure feature works in containerized deployments

User Stories

US1: Local Development Workflow

As a developer, I want to create a custom catalog for my development MCP servers so that I can easily switch between development and production gateway configurations.

bash
# Setup once
docker mcp feature enable configured-catalogs
docker mcp catalog create dev-servers
docker mcp catalog add dev-servers local-db ./local-db-server.yaml
docker mcp catalog add dev-servers test-api ./test-api-server.yaml

# Daily usage - custom servers automatically available
docker mcp gateway run --use-configured-catalogs
docker mcp tools enable local-db-query

US2: Team Shared Catalogs

As a team lead, I want to import our team's shared catalog so that all team members have access to our custom MCP servers without manual configuration.

bash
# One-time setup
docker mcp feature enable configured-catalogs
docker mcp catalog import https://internal.company.com/mcp/team-catalog.yaml

# Ongoing usage - team servers automatically available
docker mcp gateway run --use-configured-catalogs

US3: Production Server Management

As a DevOps engineer, I want to combine official Docker servers with our production-specific servers in a single gateway instance.

bash
# Production setup
docker mcp catalog create prod-monitoring  
docker mcp catalog add prod-monitoring datadog ./datadog-mcp.yaml
docker mcp catalog add prod-monitoring pagerduty ./pagerduty-mcp.yaml

# Gateway includes Docker + production servers automatically
docker mcp gateway run --use-configured-catalogs

US4: Catalog Sharing and Backup

As a team member, I want to export my custom catalog configuration so I can share it with teammates or backup my configuration.

bash
# Export custom catalog to share with team
docker mcp catalog export my-servers ./team-servers.yaml

# Team member imports the shared catalog
docker mcp catalog import ./team-servers.yaml

# Cannot export Docker's official catalog (protected)
docker mcp catalog export docker-mcp ./backup.yaml
# Error: Cannot export official Docker catalog 'docker-mcp'

US5: Quick Start with Examples

As a new user, I want to easily understand the catalog format and get started with custom catalogs by having examples based on Docker's official servers.

bash
# Create a starter catalog file with Docker Hub and Docker CLI as examples
docker mcp catalog bootstrap ./my-starter-catalog.yaml

# File contains properly formatted Docker and DockerHub entries as reference
# User can modify file to add their own servers
# Then import or use as source for other commands

docker mcp catalog import ./my-starter-catalog.yaml
# OR
docker mcp catalog add existing-catalog my-server ./my-starter-catalog.yaml

US6: Docker Desktop Compatibility

As a Docker Desktop user, I want the existing catalog functionality to continue working without any changes to my workflow.

bash
# This continues to work exactly as before - no user catalogs included
docker mcp gateway run

# Docker Desktop continues to request specific catalogs explicitly
# (Internal: docker mcp catalog show docker-mcp --format=json)

Technical Requirements

Functional Requirements

FR1: Feature Flag System

  • Feature Name: configured-catalogs
  • Storage: ~/.docker/config.json in features object
  • Activation: docker mcp feature enable configured-catalogs
  • Validation: Gateway commands validate feature enablement before using configured catalogs

FR2: Gateway Integration

  • New Flag: --use-configured-catalogs for docker mcp gateway run
  • Behavior: When enabled, includes user-managed catalogs from ~/.docker/mcp/catalog.json
  • Fallback: If configuration loading fails, continues with Docker catalog only
  • Logging: Comprehensive logging of catalog loading and server conflicts

FR3: Catalog Precedence Order

When multiple catalogs contain the same server name, last loaded wins:

  1. Built-in Gateway catalogs (future expansion point)
  2. Docker official catalog (docker-mcp.yaml)
  3. User configured catalogs (from catalog management system) [if --use-configured-catalogs]
  4. CLI-specified catalogs (--catalog and --additional-catalog flags)

FR4: Command Visibility

  • Unhide Commands: Remove Hidden: true from catalog CRUD commands
  • New Export Command: Add export <catalog-name> [output-file] command for user-managed catalogs
  • Documentation: Update command help text to reference feature flag requirement
  • Discovery: docker mcp catalog --help shows all available commands

FR5: Configuration Access

  • Plugin Mode: Full access to dockerCli.ConfigFile().Features
  • Standalone Mode: Same access pattern via Docker CLI infrastructure
  • Container Mode: Graceful degradation when config not mounted
  • Error Handling: Clear messages when config inaccessible

Non-Functional Requirements

NFR1: Backward Compatibility

  • Docker Desktop: Zero changes to existing behavior when feature not enabled
  • CLI Compatibility: All existing flags and commands work identically
  • Default Behavior: docker mcp gateway run remains unchanged
  • Migration: No existing configurations require updates

NFR2: Performance

  • Catalog Loading: Minimal overhead when loading multiple catalogs
  • Conflict Resolution: Efficient server deduplication across catalogs
  • Startup Time: Feature flag validation adds <50ms to command startup
  • Memory Usage: Catalog merging uses reasonable memory footprint

NFR3: Security

  • Feature Isolation: Disabled feature cannot access user catalogs
  • Config Validation: Validate catalog URLs and file paths for safety
  • Access Control: Respect Docker configuration directory permissions
  • Container Safety: No privilege escalation in container mode

NFR4: Usability

  • Error Messages: Clear, actionable error messages with exact commands to run
  • Documentation: Feature flag requirement clearly documented
  • Discoverability: Users can discover catalog management without external documentation
  • Logging: Gateway startup logs indicate which catalogs are active

Technical Design

Architecture Overview

text
Docker Desktop (unchanged)
โ”œโ”€โ”€ docker mcp catalog show docker-mcp --format=json
โ””โ”€โ”€ docker mcp gateway run (Docker catalog only)

Manual CLI Usage (new capability)
โ”œโ”€โ”€ docker mcp feature enable configured-catalogs  
โ”œโ”€โ”€ docker mcp catalog create/add/import (now visible)
โ”œโ”€โ”€ docker mcp gateway run --use-configured-catalogs
โ””โ”€โ”€ Automatic: Docker + User catalogs merged

Implementation Components

1. Feature Management Commands

New Commands:

bash
docker mcp feature enable configured-catalogs   # Set features.configured-catalogs=enabled
docker mcp feature disable configured-catalogs  # Set features.configured-catalogs=disabled  
docker mcp feature list                         # Show all feature flags and status

Implementation: New cmd/docker-mcp/commands/feature.go

2. Bootstrap Command (New)

New Command: docker mcp catalog bootstrap <output-file-path>

Purpose: Create a starter catalog file with Docker and Docker Hub server entries as examples, making it easy for users to understand the catalog format and quickly get started with custom catalogs.

Behavior:

  • Extracts dockerhub and docker server entries from live Docker catalog
  • Creates a properly formatted YAML catalog file at specified path
  • File is standalone (not automatically imported) - ready for user modification
  • Provides real working examples of catalog server definitions

Usage Examples:

bash
# Create starter catalog with Docker examples
docker mcp catalog bootstrap ./my-starter-catalog.yaml

# Output file contains:
# registry:
#   dockerhub:
#     description: "Docker Hub official MCP server."
#     title: "Docker Hub"
#     image: "mcp/dockerhub@sha256:..."
#     tools: [...]
#     # ... complete server definition
#   docker:
#     description: "Use the Docker CLI."
#     title: "Docker"  
#     type: "poci"
#     # ... complete server definition

# User can then modify and import
docker mcp catalog import ./my-starter-catalog.yaml

# Or use as source for copying specific servers
docker mcp catalog add my-catalog docker-hub ./my-starter-catalog.yaml

Implementation Strategy:

  1. Config Loading: Call ReadConfigWithDefaultCatalog(ctx) to load Docker catalog config
  2. YAML Reading: Call ReadCatalogFile("docker-mcp") to get raw catalog YAML
  3. Struct Parsing: Unmarshal YAML to Registry struct for Go data access
  4. Server Extraction: Extract registry.Registry["dockerhub"] and registry.Registry["docker"] entries
  5. Bootstrap Generation: Create new Registry struct with only extracted servers
  6. YAML Output: Marshal to YAML and write standalone catalog file

Error Handling:

  • Validate output path is writable
  • Handle Docker catalog access failures gracefully
  • Provide overwrite protection/confirmation for existing files

Implementation: New cmd/docker-mcp/commands/bootstrap.go and cmd/docker-mcp/catalog/bootstrap.go

3. Gateway Command Enhancement

Modified Command: docker mcp gateway run

New Flag: --use-configured-catalogs

Validation Logic:

go
func validateConfiguredCatalogsFeature(dockerCli command.Cli, useConfigured bool) error {
    if !useConfigured {
        return nil // No validation when feature not requested
    }
    
    featuresMap := dockerCli.ConfigFile().Features
    if v, ok := featuresMap["configured-catalogs"]; ok {
        if enabled, err := strconv.ParseBool(v); err == nil && enabled {
            return nil // Feature enabled
        }
    }
    
    return fmt.Errorf(`configured catalogs feature is not enabled.

To enable this experimental feature, run:
  docker mcp feature enable configured-catalogs

This feature allows the gateway to automatically include user-managed catalogs
alongside the default Docker catalog.`)
}

3. Catalog Loading Enhancement

Modified Function: cmd/docker-mcp/catalog/catalog.go:Get()

Current:

go
func Get(ctx context.Context) (Catalog, error) {
    return ReadFrom(ctx, []string{"docker-mcp.yaml"})
}

New:

go
func Get(ctx context.Context, useConfigured bool, additionalCatalogs []string) (Catalog, error) {
    var catalogSources []string
    
    // 1. Future: Built-in catalogs
    // catalogSources = append(catalogSources, getBuiltinCatalogs()...)
    
    // 2. Docker official catalog (always included)
    catalogSources = append(catalogSources, "docker-mcp.yaml")
    
    // 3. User configured catalogs (only if feature enabled)
    if useConfigured {
        configuredCatalogs, err := getConfiguredCatalogs()
        if err != nil {
            log.Printf("Warning: failed to load configured catalogs: %v", err)
        } else {
            catalogSources = append(catalogSources, configuredCatalogs...)
        }
    }
    
    // 4. CLI-specified additional catalogs  
    catalogSources = append(catalogSources, additionalCatalogs...)
    
    return ReadFrom(ctx, catalogSources)
}

func getConfiguredCatalogs() ([]string, error) {
    cfg, err := catalogConfig.ReadConfig() // Read ~/.docker/mcp/catalog.json
    if err != nil {
        return nil, err
    }
    
    var catalogFiles []string
    for name := range cfg.Catalogs {
        catalogFiles = append(catalogFiles, name + ".yaml")
    }
    return catalogFiles, nil  
}

4. Enhanced Conflict Resolution

Modified Function: cmd/docker-mcp/catalog/catalog.go:ReadFrom()

Enhanced Logging:

go
func ReadFrom(ctx context.Context, fileOrURLs []string) (Catalog, error) {
    mergedServers := map[string]Server{}
    catalogSources := make(map[string]string) // server -> source catalog

    log.Printf("Loading %d catalogs in precedence order", len(fileOrURLs))
    
    for i, fileOrURL := range fileOrURLs {
        log.Printf("Loading catalog %d/%d: %s", i+1, len(fileOrURLs), fileOrURL)
        
        servers, err := readMCPServers(ctx, fileOrURL)
        if err != nil {
            log.Printf("Warning: failed to load catalog '%s': %v", fileOrURL, err)
            continue
        }

        for serverName, server := range servers {
            if existingSource, exists := catalogSources[serverName]; exists {
                log.Printf("SERVER OVERRIDE: '%s' from '%s' replaces version from '%s'", 
                    serverName, fileOrURL, existingSource)
            } else {
                log.Printf("SERVER ADDED: '%s' from '%s'", serverName, fileOrURL)
            }
            
            mergedServers[serverName] = server
            catalogSources[serverName] = fileOrURL
        }
    }

    log.Printf("Final catalog contains %d servers from %d catalogs", 
        len(mergedServers), len(fileOrURLs))

    return Catalog{Servers: mergedServers}, nil
}

5. Export Command Implementation

New Command: docker mcp catalog export <catalog-name> [output-file]

Purpose: Export user-managed catalogs to files for sharing, backup, or migration.

Implementation: New cmd/docker-mcp/catalog/export.go

Key Features:

go
func exportCatalog(ctx context.Context, catalogName, outputFile string) error {
    // 1. Validate catalog exists and is user-managed
    if catalogName == "docker-mcp" || catalogName == DockerCatalogName {
        return fmt.Errorf("cannot export official Docker catalog '%s'", catalogName)
    }
    
    // 2. Read catalog from ~/.docker/mcp/catalogs/{catalogName}.yaml
    catalogPath, err := catalogConfig.FilePath(fmt.Sprintf("catalogs/%s.yaml", catalogName))
    if err != nil {
        return err
    }
    
    catalogData, err := os.ReadFile(catalogPath)
    if err != nil {
        return fmt.Errorf("catalog '%s' not found", catalogName)
    }
    
    // 3. Default output file if not specified
    if outputFile == "" {
        outputFile = fmt.Sprintf("./%s.yaml", catalogName)
    }
    
    // 4. Write to output file
    return os.WriteFile(outputFile, catalogData, 0644)
}

Protection Logic:

  • Official Catalog Protection: Prevent export of docker-mcp catalog
  • User Catalog Only: Only export catalogs that exist in ~/.docker/mcp/catalogs/
  • File Validation: Ensure target catalog exists before attempting export

Usage Examples:

bash
# Export to default filename (my-servers.yaml)
docker mcp catalog export my-servers

# Export to specific file
docker mcp catalog export my-servers ./shared/team-catalog.yaml

# Export for backup
docker mcp catalog export prod-monitoring ./backups/prod-$(date +%Y%m%d).yaml

6. Command Visibility Updates

Modified Files: All catalog command files in cmd/docker-mcp/catalog/

Changes: Remove Hidden: true from:

  • import.go - Import catalogs from URLs/files
  • export.go - Export user catalogs to files (new command)
  • create.go - Create empty local catalogs
  • add.go - Add servers to catalogs
  • fork.go - Duplicate existing catalogs
  • rm.go - Remove catalogs

Enhanced Help Text: Reference feature flag requirement in command descriptions.

Container Mode Support

Volume Mount Requirement:

bash
# For feature flags to work in container mode
docker run -v ~/.docker:/root/.docker docker/mcp-gateway gateway run --use-configured-catalogs

# Or mount just the config
docker run -v ~/.docker/config.json:/root/.docker/config.json docker/mcp-gateway gateway run --use-configured-catalogs

Enhanced Error Handling:

go
func validateConfiguredCatalogsFeature(dockerCli command.Cli, useConfigured bool) error {
    if !useConfigured {
        return nil
    }
    
    configFile := dockerCli.ConfigFile()
    if configFile == nil {
        return fmt.Errorf(`Docker configuration not accessible.

If running in container, mount Docker config:
  -v ~/.docker:/root/.docker
  
Or mount just the config file:  
  -v ~/.docker/config.json:/root/.docker/config.json`)
    }
    
    // Continue with feature validation...
}

Testing Strategy

Unit Tests

Test Coverage Areas

  1. Feature Flag Validation: Test enabled/disabled/missing scenarios
  2. Catalog Loading: Test precedence order and conflict resolution
  3. Error Handling: Test config inaccessible, malformed catalogs
  4. Container Mode: Test behavior without volume mounts

Key Test Cases

go
func TestCatalogPrecedenceOrder(t *testing.T) {
    // Test that CLI catalogs override configured catalogs override Docker catalog
}

func TestFeatureFlagValidation(t *testing.T) {
    // Test feature flag validation in various states
}

func TestContainerModeGracefulDegradation(t *testing.T) {
    // Test behavior when Docker config is inaccessible
}

Integration Tests

Test Scenarios

  1. End-to-End Workflow: Create catalog โ†’ Add server โ†’ Enable feature โ†’ Run gateway โ†’ Verify server availability
  2. Docker Desktop Compatibility: Verify existing workflows unchanged
  3. Multi-Catalog Conflicts: Test server override behavior across catalogs
  4. Feature Flag Lifecycle: Enable โ†’ Use โ†’ Disable โ†’ Verify disabled

Test Environment

  • Docker Desktop: Verify no regression in existing behavior
  • Standalone Binary: Verify feature works in standalone mode
  • Container: Verify graceful degradation without volume mounts

Migration Strategy

Phase 1: Implementation (No Breaking Changes)

  1. Add Feature Management: Implement docker mcp feature commands
  2. Enhance Gateway: Add --use-configured-catalogs flag with validation
  3. Update Catalog Loading: Implement precedence-based catalog merging
  4. Unhide Commands: Make catalog CRUD commands visible
  5. Comprehensive Testing: Unit and integration test coverage

Phase 2: Documentation and User Communication

  1. User Documentation: Update CLI reference and tutorials
  2. Migration Guide: Document feature enablement and workflows
  3. Release Notes: Highlight new capability and backward compatibility
  4. Community Communication: Blog post explaining enhanced catalog management

Phase 3: Future Enhancements (Optional)

  1. Docker Desktop Integration: UI for managing custom catalogs
  2. Catalog Signing: Implement signature verification for remote catalogs
  3. Default Feature: Consider making configured catalogs default in future major version
  4. Well-Known Catalogs: Add community catalog aliases

Risk Assessment

High-Impact Risks

Risk: Docker Desktop Regression

  • Probability: Low
  • Impact: High
  • Mitigation: Extensive testing, feature flag gating, unchanged default behavior

Risk: Configuration Corruption

  • Probability: Low
  • Impact: Medium
  • Mitigation: Atomic config updates, backup/restore commands, validation

Medium-Impact Risks

Risk: Performance Degradation

  • Probability: Low
  • Impact: Medium
  • Mitigation: Efficient catalog loading, caching, performance testing

Risk: User Confusion

  • Probability: Medium
  • Impact: Low
  • Mitigation: Clear error messages, comprehensive documentation, progressive disclosure

Low-Impact Risks

Risk: Container Mode Limitations

  • Probability: Medium
  • Impact: Low
  • Mitigation: Clear documentation, graceful degradation, helpful error messages

Success Metrics

User Adoption

  • Feature Enablement: Track configured-catalogs feature activation
  • Command Usage: Monitor usage of previously hidden catalog commands
  • Gateway Usage: Track --use-configured-catalogs flag adoption

Technical Metrics

  • Performance: Gateway startup time with multiple catalogs
  • Reliability: Error rates when loading configured catalogs
  • Compatibility: Docker Desktop integration regression testing results

User Experience

  • Support Requests: Reduction in catalog-related support questions
  • Documentation Engagement: Usage of new catalog management documentation
  • Community Feedback: User satisfaction with enhanced catalog workflow

Open Questions

  1. Default Behavior: Should configured catalogs eventually become the default (breaking change)?
  2. Catalog Validation: What level of validation should be applied to imported catalogs?
  3. Performance Optimization: Should catalog loading be cached between gateway runs?
  4. Docker Desktop UI: When should Docker Desktop add catalog management UI?

Conclusion

This feature specification provides a comprehensive, backward-compatible enhancement to MCP Gateway catalog management. By using Docker CLI's existing feature flag system and maintaining strict compatibility with Docker Desktop, users gain powerful catalog management capabilities while ensuring existing workflows remain unchanged.

The implementation leverages existing infrastructure (Jim Clark's multi-catalog support, David Gageot's catalog management system) to provide a complete solution with minimal risk and maximum user value.


Feature Specs Catalog Management Implementation Checklist (`docs/feature-specs/catalog-management/implementation-checklist.md`)

User-Managed Catalogs Implementation Checklist

Project Status: โœ… PHASE 1 & 2 COMPLETE - PRODUCTION READY

Last Updated: August 1, 2025
Feature Spec: feature-spec.md
Investigation Notes: /Users/masegraye/dev/docker/id-writing/scratch/mcp-gateway-investigation.md

๐ŸŽ‰ Implementation Summary

All Phase 1 & 2 implementation work has been completed and tested:

  • โœ… Feature Management System: Full TDD implementation with 8 test cases
  • โœ… Gateway Enhancement: Complete flag integration with 5 test cases
  • โœ… Catalog Loading: Multi-catalog support with 6 test cases
  • โœ… Export Command: New functionality with 4 test cases
  • โœ… Bootstrap Command: New quick-start functionality with 4 test cases
  • โœ… Command Visibility: All CRUD commands now user-accessible
  • โœ… Container Test Suite: All tests pass in Docker container environment
  • โœ… Binary Build: Successful compilation and CLI plugin installation
  • โœ… End-to-End Workflow: Complete bootstrap โ†’ add โ†’ export validation

Development Workflow & TDD Instructions

Essential Commands for Development

All commands should be run from /Users/masegraye/dev/docker/workspaces/catalog-management/mcp-gateway/:

bash
# Scoped Test-Driven Development Cycle
go test ./cmd/docker-mcp/commands           # Test specific package (fastest)
go test ./cmd/docker-mcp/...               # Test cmd tree (medium scope)
make test                                   # Test entire system (broadest scope)
make docker-mcp                            # Build and install binary (only after tests pass)
make lint-darwin                           # Run linting (only when implementation complete)

# Manual testing commands
./dist/docker-mcp --help                    # Verify binary works
./dist/docker-mcp catalog --help           # Check catalog commands
./dist/docker-mcp gateway run --help       # Check gateway flags

TDD Development Process

CRITICAL: Follow this exact workflow with progressively broader scope:

1. Red Phase - Write Failing Tests First

bash
# Test just the specific package you're working on
go test ./cmd/docker-mcp/commands    # Example: testing feature commands
# Should show failing tests for new functionality

2. Green Phase - Make Tests Pass

bash
# Write minimal implementation to make tests pass
go test ./cmd/docker-mcp/commands    # Test same package again
# Should show all tests passing in that package

3. Package Integration Test

bash
# Test all related packages together
go test ./cmd/docker-mcp/...         # Test entire cmd tree
# Should show all tests passing across packages

4. Full System Test

bash
# Test the entire system
make test
# Should show all tests passing system-wide

5. Build Phase - Verify Compilation

bash
# Only build after all tests pass
make docker-mcp
# Should build successfully and install to ~/.docker/cli-plugins/docker-mcp

6. Manual Verification

bash
# Test the actual CLI functionality
./dist/docker-mcp [your-new-command] --help
# Verify your changes work as expected

7. Refactor Phase (Optional)

bash
# Improve code while keeping tests green
go test ./path/to/package    # Test specific package after changes

8. Lint Phase (End of Implementation Only)

bash
# Only run linting when feature is complete
make lint-darwin
# Should show 0 issues

Test Categories & Strategy

Unit Tests (Primary Focus)

  • Location: Tests should be in *_test.go files alongside implementation
  • Speed: Fast (< 1 second per test file)
  • Focus: Individual function/method behavior
  • Run Command: make test

Integration Tests (Secondary)

  • Location: cmd/docker-mcp/integration_test.go and similar
  • Speed: Slower (requires Docker daemon)
  • Focus: End-to-end command workflows
  • Note: Some are skipped in normal make test runs

Manual Tests (Verification)

  • Purpose: Verify CLI behavior matches expectations
  • When: After successful build, before marking tasks complete
  • Focus: User experience and error messages

Implementation Guidelines

  1. Test First: Always write tests before implementation
  2. Small Steps: Implement one small piece at a time
  3. Green Tests: Never commit with failing tests
  4. Build Validation: Only build after tests pass
  5. Manual Check: Always verify CLI behavior manually
  6. Lint Last: Only run linting when implementation is complete

Error Handling Strategy

Test Failures

bash
make test
# If tests fail, fix the code, don't skip tests

Build Failures

bash
make docker-mcp
# If build fails, check compilation errors and fix
# Don't proceed to manual testing until build succeeds

Lint Failures (End of Development)

bash
make lint-darwin
# Fix all linting issues before marking feature complete

Baseline Verification โœ…

The following baseline tests have been verified to work:

  • make docker-mcp - Builds successfully
  • make test - All existing tests pass
  • make lint-darwin - 0 linting issues
  • CLI functionality verified working

Ready to begin TDD implementation following the above workflow.

๐Ÿงช Test Strategy Overview

Required Test Files for TDD Implementation

Each implementation section below specifies TEST FIRST requirements. These test files must be created with failing tests before writing implementation code:

Component Test File Purpose
Feature Management cmd/docker-mcp/commands/feature_test.go Test feature enable/disable/list commands
Gateway Enhancement cmd/docker-mcp/commands/gateway_test.go Test --use-configured-catalogs flag validation
Catalog Loading cmd/docker-mcp/internal/catalog/catalog_test.go Test catalog precedence and loading logic
Export Command cmd/docker-mcp/catalog/export_test.go Test export functionality and protection
Command Visibility cmd/docker-mcp/catalog/*_test.go Test unhidden commands appear in help

Test-First Workflow Reminder

bash
# 1. Write failing tests first
go test ./cmd/docker-mcp/commands -v  # Should show failing tests

# 2. Write minimal implementation  
go test ./cmd/docker-mcp/commands -v  # Should show passing tests

# 3. Test broader scope
go test ./cmd/docker-mcp/... -v      # Should show all integration tests pass

# 4. Test full system
make test                            # Should show all system tests pass

# 5. Build and verify
make docker-mcp                      # Should build successfully

Quick Context for Claude Code Sessions

What This Feature Does

Enable users to create and manage custom MCP server catalogs that automatically work with the gateway runtime, while maintaining backward compatibility with Docker Desktop through feature flag gating.

Current Architecture Status

  • โœ… Catalog CRUD System: Fully implemented by David Gageot (June-July 2025)
  • โœ… Multi-Catalog Gateway: Implemented by Jim Clark (July 21, 2025)
  • โœ… Infrastructure: All underlying systems exist and work
  • โŒ Integration Gap: Gateway runtime ignores catalog management system
  • โŒ User Discovery: Catalog management commands are hidden

Implementation Strategy

Feature Flag Approach: Use Docker CLI's existing features config system to gate new functionality, ensuring Docker Desktop compatibility.

Implementation Checklist

Phase 1: Core Implementation โœ… COMPLETED

1.1 Feature Management System โœ… COMPLETED

๐Ÿงช TEST FIRST: cmd/docker-mcp/commands/feature_test.go โœ… COMPLETED

  • Write tests for feature command structure

    go
    // Test cases implemented:
    func TestFeatureEnableCommand(t *testing.T)     // โœ… Test enabling configured-catalogs
    func TestFeatureDisableCommand(t *testing.T)    // โœ… Test disabling configured-catalogs  
    func TestFeatureListCommand(t *testing.T)       // โœ… Test listing all features and status
    func TestFeatureInvalidFeature(t *testing.T)    // โœ… Test error for unknown feature names
  • Create feature command structure โœ… COMPLETED

    • File: cmd/docker-mcp/commands/feature.go
    • Commands: enable <feature>, disable <feature>, list
    • Target: ~/.docker/config.json โ†’ features.configured-catalogs

๐Ÿงช TEST FIRST: cmd/docker-mcp/commands/feature_test.go (validation utilities) โœ… COMPLETED

  • Write tests for feature validation utilities

    go
    // Test cases implemented:
    func TestIsFeatureEnabledTrue(t *testing.T)       // โœ… Test when feature is enabled
    func TestIsFeatureEnabledFalse(t *testing.T)      // โœ… Test when feature is disabled
    func TestIsFeatureEnabledMissing(t *testing.T)    // โœ… Test when config missing
    func TestIsFeatureEnabledCorrupt(t *testing.T)    // โœ… Test when config corrupted
  • Feature validation utilities โœ… COMPLETED

    • Function: isFeatureEnabled(dockerCli command.Cli, feature string) bool
    • Handle missing config file gracefully
    • Support container mode detection
  • Integration with root command โœ… COMPLETED

    • Add feature command to cmd/docker-mcp/commands/root.go
    • Ensure proper dockerCli context passing

1.2 Gateway Command Enhancement โœ… COMPLETED

๐Ÿงช TEST FIRST: cmd/docker-mcp/commands/gateway_test.go โœ… COMPLETED

  • Write tests for gateway flag validation

    go
    // Test cases implemented:
    func TestGatewayUseConfiguredCatalogsEnabled(t *testing.T)   // โœ… Test flag works when feature enabled
    func TestGatewayUseConfiguredCatalogsDisabled(t *testing.T)  // โœ… Test flag fails when feature disabled
    func TestGatewayFeatureFlagErrorMessage(t *testing.T)        // โœ… Test error message clarity
    func TestGatewayContainerModeDetection(t *testing.T)         // โœ… Test container mode handling
    func TestGatewayNoValidationWhenFlagNotUsed(t *testing.T)    // โœ… Test no validation when flag not used
  • Add --use-configured-catalogs flag โœ… COMPLETED

    • File: cmd/docker-mcp/commands/gateway.go
    • Flag: --use-configured-catalogs (boolean)
    • Validation: Check feature flag before allowing flag usage
  • Feature validation integration โœ… COMPLETED

    • PreRunE validation for feature flag requirement
    • Clear error messages with exact enable command
    • Container mode detection and helpful errors
  • Pass flag to catalog system โœ… COMPLETED

    • Update catalog.Get() call site
    • Pass useConfigured boolean parameter

1.3 Catalog Loading Enhancement โœ… COMPLETED

๐Ÿงช TEST FIRST: cmd/docker-mcp/internal/catalog/catalog_test.go โœ… COMPLETED

  • Write tests for catalog loading logic

    go
    // Test cases implemented:
    func TestCatalogGetWithConfigured(t *testing.T)         // โœ… Test loading configured catalogs
    func TestCatalogGetWithoutConfigured(t *testing.T)      // โœ… Test default behavior unchanged
    func TestGetConfiguredCatalogsSuccess(t *testing.T)     // โœ… Test reading catalog.json
    func TestGetConfiguredCatalogsMissing(t *testing.T)     // โœ… Test missing catalog.json
    func TestGetConfiguredCatalogsCorrupt(t *testing.T)     // โœ… Test corrupted catalog.json
    func TestCatalogPrecedenceOrder(t *testing.T)           // โœ… Test Docker โ†’ Configured โ†’ CLI order
  • Update catalog.Get() signature โœ… COMPLETED

    • File: cmd/docker-mcp/internal/catalog/catalog.go
    • New function: GetWithOptions(ctx context.Context, useConfigured bool, additionalCatalogs []string) (Catalog, error)
    • Backward compatibility: Keep current Get() for existing callers
  • Implement getConfiguredCatalogs() โœ… COMPLETED

    • Read from ~/.docker/mcp/catalog.json
    • Return list of catalog file names
    • Handle missing/corrupted catalog registry gracefully
  • Implement catalog precedence logic โœ… COMPLETED

    • Order: Docker โ†’ Configured โ†’ CLI-specified
    • Use existing ReadFrom() function with ordered list
    • Comprehensive logging of loading process with warnings

1.4 Enhanced Conflict Resolution & Logging โœ… COMPLETED

๐Ÿงช TEST FIRST: cmd/docker-mcp/internal/catalog/catalog_test.go (conflict resolution) โœ… COMPLETED

  • Write tests for conflict resolution

    go
    // Test cases implemented:
    func TestCatalogPrecedenceOrder(t *testing.T)     // โœ… Test server-level precedence (architecturally correct)
    // Additional conflict resolution validated through existing ReadFrom() behavior
  • Validate ReadFrom() logging โœ… COMPLETED

    • File: cmd/docker-mcp/internal/catalog/catalog.go
    • Existing warning messages for server conflicts confirmed working
    • Server-level precedence correctly implemented
  • Server conflict handling โœ… COMPLETED

    • Confirmed server-level replacement prevents tool mixing issues
    • "Last wins" precedence behavior validated as architecturally correct
    • Gateway tool flattening works properly with resolved servers

1.5 Export Command Implementation โœ… COMPLETED

๐Ÿงช TEST FIRST: cmd/docker-mcp/commands/export_test.go โœ… COMPLETED

  • Write tests for export command

    go
    // Test cases implemented:
    func TestExportCatalogCommand(t *testing.T)           // โœ… Test successful export
    func TestExportDockerCatalogShouldFail(t *testing.T)  // โœ… Test docker-mcp protection
    func TestExportNonExistentCatalog(t *testing.T)       // โœ… Test missing catalog error
    func TestExportInvalidOutputPath(t *testing.T)        // โœ… Test file permission/path errors
  • Create export command โœ… COMPLETED

    • File: cmd/docker-mcp/catalog/export.go (new)
    • Command: export <catalog-name> <file-path>
    • Protection: Prevent export of docker-mcp official catalog
  • Export functionality โœ… COMPLETED

    • Read catalog from ~/.docker/mcp/catalogs/{name}.yaml
    • Validate catalog exists and is user-managed
    • Support for custom output file path
  • Error handling โœ… COMPLETED

    • Clear error for attempting to export official Docker catalog
    • Helpful error when catalog doesn't exist
    • File system permission error handling

1.6 Command Visibility Updates โœ… COMPLETED

๐Ÿงช TEST FIRST: Command visibility validated through CLI help output โœ… COMPLETED

  • Manual validation of command visibility

    bash
    # All commands now visible in docker mcp catalog --help:
    # โœ… add         Add a server to your catalog
    # โœ… create      Create a new catalog
    # โœ… export      Export a configured catalog to a file
    # โœ… fork        Fork a catalog
    # โœ… import      Import a catalog
    # โœ… rm          Remove a catalog
  • Unhide catalog CRUD commands โœ… COMPLETED

    • Files: cmd/docker-mcp/commands/catalog.go
    • Removed Hidden: true from all command definitions
    • All catalog management commands now user-visible
  • Update command descriptions โœ… COMPLETED

    • Export command includes clear protection messaging
    • Help text explains user-managed vs Docker catalog distinction

Phase 2: Testing & Validation โœ… COMPLETED

2.1 Unit Tests โœ… COMPLETED

  • Feature flag validation tests โœ… COMPLETED

    • Test enabled/disabled/missing scenarios (4 test cases)
    • Test Docker CLI integration
    • Test container mode behavior
  • Catalog loading tests โœ… COMPLETED

    • Test precedence order with multiple catalogs (6 test cases)
    • Test conflict resolution logging with warning messages
    • Test graceful failure handling for missing/corrupt registry
  • Export command tests โœ… COMPLETED

    • Test successful export of user catalogs
    • Test prevention of Docker catalog export
    • Test catalog not found scenarios
    • Test file permission error handling
  • Gateway integration tests โœ… COMPLETED

    • Test flag validation (5 test cases)
    • Test feature flag gating with clear error messages
    • Test container mode detection and guidance

2.2 Integration Tests โœ… COMPLETED

  • End-to-end workflow tests โœ… COMPLETED

    • All test suites pass in container environment
    • Binary builds and installs successfully as Docker CLI plugin
    • All commands visible and functional in CLI help
  • Docker Desktop compatibility tests โœ… COMPLETED

    • Verified docker mcp gateway run behavior unchanged (backward compatibility)
    • Verified existing catalog commands work as expected
    • No regression in Docker Desktop workflow
  • Container mode tests โœ… COMPLETED

    • Tests pass in Docker container environment (make test)
    • Feature flag validation works in container mode
    • Clear error messages for missing config scenarios

2.3 Manual Testing Scenarios โœ… COMPLETED

  • Development workflow testing โœ… COMPLETED

    • Feature enable/disable cycle verified working
    • All catalog commands now visible in docker mcp catalog --help
    • Export command protection working correctly
    • Binary installation to ~/.docker/cli-plugins/docker-mcp successful
  • Multi-catalog testing โœ… COMPLETED

    • Server-level precedence correctly implemented and tested
    • Warning logging for overlapping servers verified working
    • Architecture validated as correct for tool flattening

Phase 2: Bootstrap Command Implementation

2.1 Bootstrap Command Design โœ… COMPLETED

Command Name: docker mcp catalog bootstrap <output-file-path>

Purpose: Create a starter catalog file with Docker and Docker Hub server entries as examples, making it easy for users to understand the catalog format and get started with custom catalogs.

๐Ÿงช TEST FIRST: cmd/docker-mcp/commands/bootstrap_test.go โœ… COMPLETED

  • Write tests for bootstrap command
    go
    // Test cases implemented:
    func TestBootstrapCatalogCommand(t *testing.T)        // โœ… Test successful bootstrap creation
    func TestBootstrapExistingFile(t *testing.T)          // โœ… Test overwrite protection/confirmation
    func TestBootstrapInvalidPath(t *testing.T)           // โœ… Test invalid output path handling
    func TestBootstrapDockerEntriesExtraction(t *testing.T) // โœ… Test Docker/DockerHub entry extraction

Implementation Strategy:

  1. Config loading: Call ReadConfigWithDefaultCatalog(ctx) to load Docker catalog
  2. YAML reading: Call ReadCatalogFile("docker-mcp") to get raw catalog YAML
  3. Struct parsing: Unmarshal to Registry struct for Go data access
  4. Server extraction: Extract registry.Registry["dockerhub"] and registry.Registry["docker"]
  5. Bootstrap generation: Create new Registry with only extracted servers
  6. File creation: Marshal to YAML and write standalone catalog file

Expected User Workflow:

bash
# Create bootstrap catalog with Docker examples
docker mcp catalog bootstrap ./my-custom-catalog.yaml

# User modifies the file to add their own servers
# User can then import it
docker mcp catalog import ./my-custom-catalog.yaml

# Or use it as source for adding individual servers
docker mcp catalog add existing-catalog my-server ./my-custom-catalog.yaml

Implementation Tasks: โœ… ALL COMPLETED

  • Create bootstrap command โœ… COMPLETED

    • File: cmd/docker-mcp/commands/bootstrap.go (new)
    • Command: bootstrap <output-file-path>
    • Internal calls to ReadConfigWithDefaultCatalog() and ReadCatalogFile()
  • Bootstrap functionality โœ… COMPLETED

    • File: cmd/docker-mcp/catalog/bootstrap.go (new)
    • Extract Docker and DockerHub entries from live catalog using YAML parsing
    • Generate properly formatted YAML catalog structure with extracted servers
    • File overwrite protection with clear error messages
  • Error handling โœ… COMPLETED

    • Validate output path is writable with directory creation
    • Handle Docker catalog access failures gracefully
    • Clear error messages for file conflicts and missing servers
  • Integration with catalog command โœ… COMPLETED

    • Added bootstrap command to cmd/docker-mcp/commands/catalog.go
    • Comprehensive help text and examples
    • Full CLI integration and visibility

End-to-End Validation: โœ… COMPLETED

  • Bootstrap file creation: Successfully creates YAML with Docker and DockerHub servers
  • Catalog add integration: Bootstrap file works as source for catalog add command
  • Server extraction: Individual servers can be copied from bootstrap file to catalogs
  • Export roundtrip: Full workflow (bootstrap โ†’ add โ†’ export) validated
  • Real-world usage: Tested with actual Docker catalog data and server definitions

Phase 3: Documentation & Polish

3.1 Documentation Updates

  • CLI reference updates

    • Update generated docs for newly visible commands
    • Document feature flag requirement
    • Document new bootstrap command workflow
    • Provide usage examples
  • User workflow documentation

    • Development workflow example including bootstrap
    • Production setup guide
    • Container deployment instructions

3.2 Error Handling Polish

  • Comprehensive error messages

    • Feature not enabled โ†’ exact enable command
    • Container mode โ†’ volume mount instructions
    • Catalog loading failures โ†’ helpful diagnostics
  • Logging improvements

    • Structured logging for catalog operations
    • Clear startup messages about active catalogs
    • Performance timing for catalog loading

Phase 4: Advanced Features (Future)

4.1 Performance Optimizations

  • Catalog caching
    • Cache loaded catalogs between gateway runs
    • Invalidate cache on catalog updates
    • Performance benchmarking

4.2 Enhanced Validation

  • Catalog URL validation
    • HTTPS requirement for remote catalogs
    • URL safety validation
    • Optional signature verification

4.3 Docker Desktop Integration

  • UI for catalog management
    • List configured catalogs in Docker Desktop
    • Enable/disable specific catalogs
    • Import catalogs via UI

Progress Tracking

Completed Analysis Work โœ…

  • Architecture Investigation: Complete understanding of existing systems
  • Git Blame Analysis: Identified key contributors and implementation timeline
  • Docker Desktop Integration: Understood compatibility requirements
  • Binary Distribution Analysis: Confirmed feature flag system works across all modes
  • Feature Flag Research: Identified Docker CLI features system as perfect solution
  • Implementation Planning: Complete technical design and user workflows
  • Feature Specification: Comprehensive spec document created
  • Risk Assessment: Identified and mitigated major risks

Current Status

โœ… PHASE 1 & 2 IMPLEMENTATION COMPLETE - PRODUCTION READY

All Phase 1 & 2 implementation, testing, and validation work is complete. The feature is ready for production use with:

  • 27 comprehensive test cases covering all functionality (Phase 1: 23 tests, Phase 2: 4 tests)
  • Full TDD implementation with test-first development methodology
  • Container environment validation - all tests pass in make test
  • End-to-End workflow validation - complete bootstrap โ†’ add โ†’ export tested
  • Backward compatibility - no changes to existing Docker Desktop workflows
  • Production-ready binary - builds and installs successfully as Docker CLI plugin

Key Achievements:

  • Users can now enable configured-catalogs feature and use custom catalogs alongside Docker's official catalog with full CLI management capabilities
  • New users can quickly get started with the bootstrap command to understand catalog format and create starter files with real Docker server examples

Key Implementation Notes

Critical Success Factors

  1. Maintain Docker Desktop Compatibility: Never change default behavior of docker mcp gateway run
  2. Feature Flag Gating: All new functionality MUST be gated behind configured-catalogs feature
  3. Graceful Degradation: System must work properly when config is inaccessible
  4. Clear User Communication: Error messages must provide exact commands to fix issues

Technical Constraints

  1. Backward Compatibility: All existing command signatures and behaviors preserved
  2. Container Support: Feature must work in container mode with proper volume mounts
  3. Performance: Catalog loading must not significantly impact gateway startup time
  4. Security: No privilege escalation or unsafe file operations

Architecture Decisions Made

  1. Feature Flag System: Use Docker CLI's existing features config approach
  2. Catalog Precedence: Last-loaded-wins for server conflicts (Docker โ†’ Configured โ†’ CLI)
  3. Command Structure: Add --use-configured-catalogs flag rather than change defaults
  4. Error Handling: Fail-safe approach where config problems disable feature rather than break gateway

File Locations Reference

Implementation Target Files

  • Feature Commands: cmd/docker-mcp/commands/feature.go (new)
  • Export Command: cmd/docker-mcp/catalog/export.go (new)
  • Gateway Enhancement: cmd/docker-mcp/commands/gateway.go
  • Catalog Loading: cmd/docker-mcp/catalog/catalog.go
  • Command Visibility: cmd/docker-mcp/catalog/{import,export,create,add,fork,rm}.go

Key Reference Files

  • Command Structure: cmd/docker-mcp/commands/root.go
  • Docker CLI Integration: cmd/docker-mcp/main.go:33-35
  • Config Pattern: cli/cli/config/configfile/file.go:120 (Features map)
  • Storage Pattern: cmd/docker-mcp/internal/config/readwrite.go

Investigation Documentation

  • Detailed Investigation: /Users/masegraye/dev/docker/id-writing/scratch/mcp-gateway-investigation.md
  • Feature Specification: docs/feature-specs/catalog-management/feature-spec.md

Contact Information

Primary Technical Contact: Jim Clark (@slimslenderslacks)

  • Implemented multi-catalog gateway support (July 21, 2025)
  • Best person to consult for architecture questions

Secondary Contact: David Gageot

  • Implemented catalog management system (June-July 2025)
  • Expert on catalog CRUD operations and storage patterns

Quick Start for New Claude Code Sessions

  1. Read the feature spec: Start with feature-spec.md for complete context
  2. Check current status: Review completed items in this checklist
  3. Start implementation: Begin with Phase 1.1 (Feature Management System)
  4. Test thoroughly: Each component must work in plugin, standalone, and container modes
  5. Maintain compatibility: Docker Desktop behavior must never change

Key Commands to Validate Success:

bash
# Phase 1: Configured catalogs workflow
docker mcp feature enable configured-catalogs
docker mcp catalog create my-servers  
docker mcp catalog add my-servers test-server ./server.yaml
docker mcp catalog export my-servers ./backup.yaml
docker mcp gateway run --use-configured-catalogs
# Gateway should start with both Docker servers AND test-server available

# Phase 2: Bootstrap workflow for new users
docker mcp catalog bootstrap ./starter-catalog.yaml
# Creates file with Docker and DockerHub server examples
docker mcp catalog create custom-servers
docker mcp catalog add custom-servers dockerhub ./starter-catalog.yaml
# Copies Docker Hub server from bootstrap file to custom catalog

# Validate export protection
docker mcp catalog export docker-mcp ./should-fail.yaml
# Should fail with: "Cannot export official Docker catalog 'docker-mcp'"

Generator Reference Mcp (`docs/generator/reference/mcp.md`)

docker mcp

Manage MCP servers and clients

Subcommands

Name Description
catalog Manage MCP server catalogs
client Manage MCP clients
config Manage the configuration
feature Manage experimental features
gateway Manage the MCP Server gateway
oauth Manage OAuth app authorizations
secret Manage secrets in the local OS Keychain
server Manage servers
tools Manage tools
version Show the version information

Options

Name Type Default Description
-v, --version bool Print version information and quit

Description

The MCP Gateway is Docker's open-source enterprise solution for orchestrating
Model Context Protocol (MCP) servers and clients.

For more information see Docker MCP and
the public GitHub repository.


Generator Reference Mcp Catalog (`docs/generator/reference/mcp_catalog.md`)

docker mcp catalog

Manage MCP server catalogs for organizing and configuring custom MCP servers alongside Docker's official catalog.

Aliases

docker mcp catalog, docker mcp catalogs

Subcommands

Name Description
add Add a server to a catalog
bootstrap Create a starter catalog file with Docker and Docker Hub server entries as examples
create Create a new empty catalog
export Export a configured catalog to a file
fork Create a copy of an existing catalog
import Import a catalog from URL or file
init Initialize the catalog system
ls List all configured catalogs
reset Reset the catalog system
rm Remove a catalog
show Display catalog contents
update Update catalog(s) from remote sources

Generator Reference Mcp Catalog Add (`docs/generator/reference/mcp_catalog_add.md`)

docker mcp catalog add

Add an MCP server definition to an existing catalog by copying it from another catalog file.
The server definition includes all configuration, tools, and metadata.

Options

Name Type Default Description
--force bool Overwrite existing server in the catalog

Generator Reference Mcp Catalog Bootstrap (`docs/generator/reference/mcp_catalog_bootstrap.md`)

docker mcp catalog bootstrap

Create a starter catalog file with Docker Hub and Docker CLI server entries as examples.
This command extracts the official Docker server definitions and creates a properly formatted
catalog file that users can modify and use as a foundation for their custom catalogs.

The output file is standalone and not automatically imported - users can modify it and then
import it or use it as a source for the 'catalog add' command.


Generator Reference Mcp Catalog Create (`docs/generator/reference/mcp_catalog_create.md`)

docker mcp catalog create

Create a new empty catalog for organizing custom MCP servers. The catalog will be stored locally and can be populated using 'docker mcp catalog add'.


Generator Reference Mcp Catalog Export (`docs/generator/reference/mcp_catalog_export.md`)

docker mcp catalog export

Export a user-managed catalog to a file. This command only works with catalogs
that have been imported or configured manually. The canonical Docker MCP catalog
cannot be exported as it is managed by Docker.


Generator Reference Mcp Catalog Fork (`docs/generator/reference/mcp_catalog_fork.md`)

docker mcp catalog fork

Create a new catalog by copying all servers from an existing catalog. Useful for creating variations of existing catalogs.


Generator Reference Mcp Catalog Import (`docs/generator/reference/mcp_catalog_import.md`)

docker mcp catalog import

Import an MCP server catalog from a URL or local file. The catalog will be downloaded
and stored locally for use with the MCP gateway.

When --mcp-registry flag is used, the argument must be an existing catalog name, and the
command will import servers from the MCP registry URL into that catalog.

Options

Name Type Default Description
--dry-run bool Show Imported Data but do not update the Catalog
--mcp-registry string Import server from MCP registry URL into existing catalog

Generator Reference Mcp Catalog Init (`docs/generator/reference/mcp_catalog_init.md`)

docker mcp catalog init

Initialize the local catalog management system by creating the necessary configuration files and directories.


Generator Reference Mcp Catalog Ls (`docs/generator/reference/mcp_catalog_ls.md`)

docker mcp catalog ls

List all configured catalogs including Docker's official catalog and any locally managed catalogs.

Options

Name Type Default Description
--format format Output format. Supported: "json", "yaml".

Generator Reference Mcp Catalog Reset (`docs/generator/reference/mcp_catalog_reset.md`)

docker mcp catalog reset

Reset the local catalog management system by removing all user-managed catalogs and configuration. This does not affect Docker's official catalog.

Aliases

docker mcp catalog reset, docker mcp catalog empty


Generator Reference Mcp Catalog Rm (`docs/generator/reference/mcp_catalog_rm.md`)

docker mcp catalog rm

Remove a locally configured catalog. This will delete the catalog and all its server definitions.
The Docker official catalog cannot be removed.


Generator Reference Mcp Catalog Show (`docs/generator/reference/mcp_catalog_show.md`)

docker mcp catalog show

Display the contents of a catalog including all server definitions and metadata.
If no name is provided, shows the Docker official catalog.

Options

Name Type Default Description
--format format Supported: "json", "yaml".

Generator Reference Mcp Catalog Update (`docs/generator/reference/mcp_catalog_update.md`)

docker mcp catalog update

Update one or more catalogs by re-downloading from their original sources.
If no name is provided, updates all catalogs that have remote sources.


Generator Reference Mcp Client (`docs/generator/reference/mcp_client.md`)

docker mcp client

Manage MCP clients

Subcommands

Name Description
connect Connect the Docker MCP Toolkit to a client. Supported clients: claude-code claude-desktop cline codex continue crush cursor gemini goose gordon kiro lmstudio opencode sema4 vscode zed
disconnect Disconnect the Docker MCP Toolkit from a client. Supported clients: claude-code claude-desktop cline codex continue crush cursor gemini goose gordon kiro lmstudio opencode sema4 vscode zed
ls List client configurations

Generator Reference Mcp Client Connect (`docs/generator/reference/mcp_client_connect.md`)

docker mcp client connect

Connect the Docker MCP Toolkit to a client. Supported clients: claude-code claude-desktop cline codex continue crush cursor gemini goose gordon kiro lmstudio opencode sema4 vscode zed

Options

Name Type Default Description
-g, --global bool Change the system wide configuration or the clients setup in your current git repo.
-q, --quiet bool Only display errors.

Generator Reference Mcp Client Disconnect (`docs/generator/reference/mcp_client_disconnect.md`)

docker mcp client disconnect

Disconnect the Docker MCP Toolkit from a client. Supported clients: claude-code claude-desktop cline codex continue crush cursor gemini goose gordon kiro lmstudio opencode sema4 vscode zed

Options

Name Type Default Description
-g, --global bool Change the system wide configuration or the clients setup in your current git repo.
-q, --quiet bool Only display errors.

Generator Reference Mcp Client Ls (`docs/generator/reference/mcp_client_ls.md`)

docker mcp client ls

List client configurations

Options

Name Type Default Description
-g, --global bool Change the system wide configuration or the clients setup in your current git repo.
--json bool Print as JSON.

Generator Reference Mcp Config (`docs/generator/reference/mcp_config.md`)

docker mcp config

Manage the configuration

Subcommands

Name Description
read Read the configuration
reset Reset the configuration
write Write the configuration

Generator Reference Mcp Config Reset (`docs/generator/reference/mcp_config_reset.md`)

docker mcp config reset

Reset the configuration


Generator Reference Mcp Config Write (`docs/generator/reference/mcp_config_write.md`)

docker mcp config write

Write the configuration


Generator Reference Mcp Feature (`docs/generator/reference/mcp_feature.md`)

docker mcp feature

Manage experimental features for Docker MCP Gateway.

Features are stored in your Docker configuration file (~/.docker/config.json)
and control optional functionality that may change in future versions.

Subcommands

Name Description
disable Disable an experimental feature
enable Enable an experimental feature
ls List all available features and their status

Generator Reference Mcp Feature Disable (`docs/generator/reference/mcp_feature_disable.md`)

docker mcp feature disable

Disable an experimental feature that was previously enabled.


Generator Reference Mcp Feature Enable (`docs/generator/reference/mcp_feature_enable.md`)

docker mcp feature enable

Enable an experimental feature.

Available features:
oauth-interceptor Enable GitHub OAuth flow interception for automatic authentication
mcp-oauth-dcr Enable Dynamic Client Registration (DCR) for automatic OAuth client setup
dynamic-tools Enable internal MCP management tools (mcp-find, mcp-add, mcp-remove)
profiles Enable profile management (docker mcp profile )
tool-name-prefix Prefix all tool names with server name to avoid conflicts


Generator Reference Mcp Feature List (`docs/generator/reference/mcp_feature_list.md`)

docker mcp feature list

List all available experimental features and show whether they are enabled or disabled.


Generator Reference Mcp Feature Ls (`docs/generator/reference/mcp_feature_ls.md`)

docker mcp feature ls

List all available experimental features and show whether they are enabled or disabled.

Aliases

docker mcp feature ls, docker mcp feature list


Generator Reference Mcp Gateway (`docs/generator/reference/mcp_gateway.md`)

docker mcp gateway

Manage the MCP Server gateway

Subcommands

Name Description
run Run the gateway

Generator Reference Mcp Gateway Run (`docs/generator/reference/mcp_gateway_run.md`)

docker mcp gateway run

Run the gateway

Options

Name Type Default Description
--additional-catalog stringSlice Additional catalog paths must resolve under ~/.docker/mcp/catalogs/
--additional-config stringSlice Additional config paths to merge with the default config.yaml
--additional-registry stringSlice Additional registry paths to merge with the default registry.yaml
--additional-tools-config stringSlice Additional tools paths to merge with the default tools.yaml
--allow-unauthenticated bool Allow unauthenticated HTTP/SSE gateway requests
--block-network bool Block tools from accessing forbidden network resources
--block-secrets bool true Block secrets from being/received sent to/from tools
--catalog stringSlice [docker-mcp.yaml] Catalog paths must resolve under ~/.docker/mcp/catalogs/
--config stringSlice [config.yaml] Paths to the config files (absolute or relative to ~/.docker/mcp/)
--cpus int 1 CPUs allocated to each MCP Server (default is 1)
--debug-dns bool Debug DNS resolution
--dry-run bool Start the gateway but do not listen for connections (useful for testing the configuration)
--enable-all-servers bool Enable all servers in the catalog (instead of using individual --servers options)
--host string Host or IP address to bind TCP transports to
--interceptor stringArray List of interceptors to use (format: when:type:path, e.g. 'before:exec:/bin/path')
--log-calls bool true Log calls to the tools
--long-lived bool Containers are long-lived and will not be removed until the gateway is stopped, useful for stateful servers
--mcp-registry stringSlice MCP registry URLs to fetch servers from (can be repeated)
--memory string 2Gb Memory allocated to each MCP Server (default is 2Gb)
--oci-ref stringArray OCI image references to use
--port int 0 TCP port to listen on (default is to listen on stdio)
--preserve-tool-schema-dialect bool Relay tool schemas with the JSON Schema dialect the server declared, instead of translating pre-2020-12 dialects
--registry stringSlice [registry.yaml] Paths to the registry files (absolute or relative to ~/.docker/mcp/)
--secrets string docker-desktop Colon separated paths to search for secrets. Can be docker-desktop or a path to a .env file (default to using Docker Desktop's secrets API)
--servers stringSlice Names of the servers to enable (if non empty, ignore --registry flag)
--static bool Enable static mode (aka pre-started servers)
--tools stringSlice List of tools to enable
--tools-config stringSlice [tools.yaml] Paths to the tools files (absolute or relative to ~/.docker/mcp/)
--transport string stdio stdio, sse or streaming. Uses MCP_GATEWAY_AUTH_TOKEN environment variable for localhost authentication to prevent dns rebinding attacks.
--verbose bool Verbose output
--verify-signatures bool true Verify signatures of Docker MCP server images
--watch bool true Watch for changes and reconfigure the gateway

Generator Reference Mcp Import (`docs/generator/reference/mcp_import.md`)

docker mcp import

Import and parse a server definition from an official MCP registry URL.

This command fetches the server definition from the provided URL, parses it as a ServerDetail,
converts it to the internal Server format, and displays the results.

Example:
docker mcp officialregistry import https://registry.example.com/servers/my-server

Options

Name Type Default Description
--catalog string import to local catalog
--mcp-registry string import from MCP registry format
--push bool push the new server artifact

Generator Reference Mcp Oauth (`docs/generator/reference/mcp_oauth.md`)

docker mcp oauth

Manage OAuth app authorizations

Subcommands

Name Description
authorize Authorize the specified OAuth app.
ls List available OAuth apps.
revoke Revoke the specified OAuth app.

Generator Reference Mcp Oauth Authorize (`docs/generator/reference/mcp_oauth_authorize.md`)

docker mcp oauth authorize

Authorize the specified OAuth app.

Options

Name Type Default Description
--open-browser bool Open the authorization URL in the default browser automatically
--scopes string OAuth scopes to request (space-separated)

Generator Reference Mcp Oauth Ls (`docs/generator/reference/mcp_oauth_ls.md`)

docker mcp oauth ls

List available OAuth apps.

Options

Name Type Default Description
--json bool Print as JSON.

Generator Reference Mcp Oauth Revoke (`docs/generator/reference/mcp_oauth_revoke.md`)

docker mcp oauth revoke

Revoke the specified OAuth app.


Generator Reference Mcp Policy (`docs/generator/reference/mcp_policy.md`)

docker mcp policy

Manage secret policies

Aliases

docker mcp policy, docker mcp policies

Subcommands

Name Description
dump Dump the policy content
set Set a policy for secret management in Docker Desktop

Generator Reference Mcp Policy Dump (`docs/generator/reference/mcp_policy_dump.md`)

docker mcp policy dump

Dump the policy content


Generator Reference Mcp Policy Set (`docs/generator/reference/mcp_policy_set.md`)

docker mcp policy set

Set a policy for secret management in Docker Desktop


Generator Reference Mcp Secret (`docs/generator/reference/mcp_secret.md`)

docker mcp secret

Manage secrets in the local OS Keychain

Subcommands

Name Description
ls List all secrets from the local OS Keychain as well as any active Secrets Engine provider
rm Remove secrets from the local OS Keychain
set Set a secret in the local OS Keychain

Generator Reference Mcp Secret Ls (`docs/generator/reference/mcp_secret_ls.md`)

docker mcp secret ls

List all secrets from the local OS Keychain as well as any active Secrets Engine provider

Options

Name Type Default Description
--json bool Print as JSON.

Generator Reference Mcp Secret Rm (`docs/generator/reference/mcp_secret_rm.md`)

docker mcp secret rm

Remove secrets from the local OS Keychain

Options

Name Type Default Description
--all bool Remove all secrets

Generator Reference Mcp Secret Set (`docs/generator/reference/mcp_secret_set.md`)

docker mcp secret set

Set a secret in the local OS Keychain

Examples

Pass the secret via STDIN

console
echo my-secret-password | docker mcp secret set postgres_password

Generator Reference Mcp Server (`docs/generator/reference/mcp_server.md`)

docker mcp server

Manage servers

Subcommands

Name Description
disable Disable a server or multiple servers
enable Enable a server or multiple servers
init Initialize a new MCP server project
inspect Get information about a server or inspect an OCI artifact
ls List enabled servers
reset Disable all the servers

Generator Reference Mcp Server Disable (`docs/generator/reference/mcp_server_disable.md`)

docker mcp server disable

Disable a server or multiple servers

Aliases

docker mcp server disable, docker mcp server remove, docker mcp server rm


Generator Reference Mcp Server Enable (`docs/generator/reference/mcp_server_enable.md`)

docker mcp server enable

Enable a server or multiple servers

Aliases

docker mcp server enable, docker mcp server add


Generator Reference Mcp Server Import (`docs/generator/reference/mcp_server_import.md`)

docker mcp server import

Import a server

Options

Name Type Default Description
--push bool push the new server artifact

Generator Reference Mcp Server Init (`docs/generator/reference/mcp_server_init.md`)

docker mcp server init

Initialize a new MCP server project in the specified directory with boilerplate code, Dockerfile, and compose.yaml

Options

Name Type Default Description
--language string go Programming language for the server (currently only 'go' is supported)
--template string basic Template to use (basic, chatgpt-app-basic)

Generator Reference Mcp Server Inspect (`docs/generator/reference/mcp_server_inspect.md`)

docker mcp server inspect

Get information about a server or inspect an OCI artifact


Generator Reference Mcp Server List (`docs/generator/reference/mcp_server_list.md`)

docker mcp server list

List enabled servers

Aliases

docker mcp server list, docker mcp server ls

Options

Name Type Default Description
--json bool Output in JSON format

Generator Reference Mcp Server Ls (`docs/generator/reference/mcp_server_ls.md`)

docker mcp server ls

List enabled servers

Aliases

docker mcp server ls, docker mcp server list

Options

Name Type Default Description
--json bool Output in JSON format

Generator Reference Mcp Server Reset (`docs/generator/reference/mcp_server_reset.md`)

docker mcp server reset

Disable all the servers


Generator Reference Mcp Tools (`docs/generator/reference/mcp_tools.md`)

docker mcp tools

Manage tools

Subcommands

Name Description
call Call a tool
count Count tools
disable disable one or more tools
enable enable one or more tools
inspect Inspect a tool
ls List tools

Options

Name Type Default Description
--format string list Output format (json|list)
--gateway-arg stringSlice Additional arguments passed to the gateway
--verbose bool Verbose output
--version string 2 Version of the gateway

Generator Reference Mcp Tools Call (`docs/generator/reference/mcp_tools_call.md`)

docker mcp tools call

Call a tool

Options

Name Type Default Description
--format string list Output format (json|list)
--gateway-arg stringSlice Additional arguments passed to the gateway
--verbose bool Verbose output
--version string 2 Version of the gateway

Generator Reference Mcp Tools Count (`docs/generator/reference/mcp_tools_count.md`)

docker mcp tools count

Count tools

Options

Name Type Default Description
--format string list Output format (json|list)
--gateway-arg stringSlice Additional arguments passed to the gateway
--verbose bool Verbose output
--version string 2 Version of the gateway

Generator Reference Mcp Tools Disable (`docs/generator/reference/mcp_tools_disable.md`)

docker mcp tools disable

disable one or more tools

Options

Name Type Default Description
--format string list Output format (json|list)
--gateway-arg stringSlice Additional arguments passed to the gateway
--server string Specify which server provides the tools (optional, will auto-discover if not provided)
--verbose bool Verbose output
--version string 2 Version of the gateway

Generator Reference Mcp Tools Enable (`docs/generator/reference/mcp_tools_enable.md`)

docker mcp tools enable

enable one or more tools

Options

Name Type Default Description
--format string list Output format (json|list)
--gateway-arg stringSlice Additional arguments passed to the gateway
--server string Specify which server provides the tools (optional, will auto-discover if not provided)
--verbose bool Verbose output
--version string 2 Version of the gateway

Generator Reference Mcp Tools Inspect (`docs/generator/reference/mcp_tools_inspect.md`)

docker mcp tools inspect

Inspect a tool

Options

Name Type Default Description
--format string list Output format (json|list)
--gateway-arg stringSlice Additional arguments passed to the gateway
--verbose bool Verbose output
--version string 2 Version of the gateway

Generator Reference Mcp Tools List (`docs/generator/reference/mcp_tools_list.md`)

docker mcp tools list

List tools

Aliases

docker mcp tools list, docker mcp tools ls

Options

Name Type Default Description
--format string list Output format (json|list)
--gateway-arg stringSlice Additional arguments passed to the gateway
--verbose bool Verbose output
--version string 2 Version of the gateway

Generator Reference Mcp Tools Ls (`docs/generator/reference/mcp_tools_ls.md`)

docker mcp tools ls

List tools

Aliases

docker mcp tools ls, docker mcp tools list

Options

Name Type Default Description
--format string list Output format (json|list)
--gateway-arg stringSlice Additional arguments passed to the gateway
--verbose bool Verbose output
--version string 2 Version of the gateway

Generator Reference Mcp Version (`docs/generator/reference/mcp_version.md`)

docker mcp version

Show the version information


--- METRICS ---