Architectural Overview
Relevant source files
The following files were used as context for generating this wiki page:- README.md
- CONTRIBUTING.md
- PHASE1_IMPLEMENTATION.md
- internal/dokku-api/client.go
- internal/dokku-api/ssh_integration_test.go
- internal/server-plugin/domain/server-plugin.go
- internal/server-plugins/app/plugin.go
- internal/server-plugins/core/plugin.go
- internal/server-plugins/deployment/infrastructure/deployment_infrastructure.go
- internal/dokku-api/client_blacklist_test.go
- scripts/setup-dokku-local.sh
- internal/server-plugins/onboarding/plugin.go
- internal/server-plugin/application/registry_test.go
The Dokku MCP (Model Context Protocol) server is a Go application designed to expose Dokku's management capabilities to Large Language Models (LLMs) and other agentic tools. The architecture is centered around Domain-Driven Design (DDD) principles, featuring a modular, plugin-based system that allows for clear separation of concerns and extensibility.
The system's primary function is to translate MCP requests into Dokku CLI commands executed over SSH. It provides a structured and secure interface, abstracting the complexities of direct Dokku interaction. Key architectural features include a layered design, a dynamic plugin registry, a robust Dokku API client with built-in security, and asynchronous operation handling for long-running tasks like application deployments.
Sources: README.md:5-9, README.md:202-207, CONTRIBUTING.md:69-70
Core Principles
The server's architecture is founded on Domain-Driven Design (DDD) and a plugin-based system, ensuring a clean separation of concerns and modularity.
Layered Architecture (DDD)
The project adheres to a classic layered architecture, which isolates business logic from infrastructure details. This separation simplifies development, testing, and maintenance.
Sources: README.md:202-207, CONTRIBUTING.md:69-70
The following diagram illustrates the primary layers and their dependencies.
| Layer | Path Prefix | Description |
|---|---|---|
| Domain | internal/*/domain | Contains the core business logic, entities, value objects, and repository interfaces. It is the heart of the business rules and has no dependencies on other layers. |
| Application | internal/*/application | Orchestrates use cases by coordinating domain objects. It does not contain business logic itself but directs the domain layer to fulfill requests. |
| Infrastructure | internal/*/infrastructure | Provides concrete implementations of the interfaces defined in the domain layer. This includes the Dokku API client, database access, and interactions with other external services. |
Sources: README.md:202-207, CONTRIBUTING.md:69-70, README.md:211-218
Plugin-Based System
The server's functionality is organized into plugins, each encapsulating a specific set of Dokku features (e.g., app, core, deployment). This design allows features to be developed, managed, and enabled/disabled independently.
Plugins are discovered and registered at runtime. A plugin can be activated based on whether its corresponding Dokku plugin is installed on the target server, or it can be a "core" plugin that is always active.
Sources: README.md:206-207, internal/server-plugin/application/registry_test.go:140-149
The core of the plugin system is the ServerPlugin interface, which acts as a container for different capability providers.
This diagram shows that a ServerPlugin can implement one or more provider interfaces to expose its capabilities.
Sources: internal/server-plugin/domain/server-plugin.go:11-48, internal/server-plugins/app/plugin.go:29-35
Each plugin can expose three types of capabilities to the MCP client:
- Resources: Read-only data sources, like a list of applications (
dokku://apps/list). - Tools: Executable functions that perform actions, such as
create_appordeploy_app. - Prompts: Pre-defined templates to guide LLMs in performing complex tasks, like
app_doctorfor diagnostics.
Sources: internal/server-plugins/app/plugin.go:60-99, internal/server-plugins/onboarding/plugin.go:41-65
All plugins are registered using Uber FX for dependency injection, grouped by the server_plugins tag.
Sources: internal/server-plugins/app/plugin.go:449-453
Dokku API Client
The dokku-api component is the infrastructure-layer module responsible for all communication with the Dokku host. It acts as a client for the Dokku CLI, executing commands over SSH.
*Sources: README.md:215, internal/dokku-api/client.go
Command Execution Flow
When a service needs to interact with Dokku, it uses the DokkuClient. The client constructs and executes an SSH command, handles authentication, applies timeouts, and parses the output.
The following diagram shows the sequence of executing a Dokku command.
This sequence shows the steps from a service request to the final parsed response, including security validation and SSH command preparation.
Sources: internal/dokku-api/client.go:103-120, internal/dokku-api/client.go:134-142, internal/dokku-api/ssh_integration_test.go:97-106
Key Features
- SSH Connection Management: Manages SSH connection details, including host, port, user, and authentication method (private key or ssh-agent). It constructs the base SSH arguments, ensuring PTY allocation (
-t) as required by Dokku.
Sources: internal/dokku-api/ssh_integration_test.go:25-36, internal/dokku-api/ssh_integration_test.go:60-69 - Security:
- Command Blacklisting: A configurable list of command patterns (e.g.,
destroy,uninstall) can be blocked from execution.
Sources: README.md:41, internal/dokku-api/client.go:27-32, internal/dokku-api/client_blacklist_test.go:32-40 - Argument Sanitization: Commands and arguments are validated to prevent injection of dangerous characters like
;,|, and$.
Sources: internal/dokku-api/client.go:36-50, internal/dokku-api/client_blacklist_test.go:76-91
- Command Blacklisting: A configurable list of command patterns (e.g.,
- JSON-First Parsing: The client attempts to execute commands with a
--format jsonflag. If the command succeeds and returns valid JSON, it is parsed directly. If it fails or returns non-JSON text, the client "remembers" this and falls back to text-based parsing for subsequent calls to that command.
Sources: internal/dokku-api/client.go:303-333 - Caching: A cache manager can be enabled to cache the results of commands, reducing redundant SSH calls.
Sources: internal/dokku-api/client.go:108-115
Asynchronous Deployment Tracking
To handle long-running operations like application builds, which can exceed SSH timeouts, the system uses an asynchronous tracking mechanism. This was a key improvement to move away from a "fire-and-forget" approach.
Sources: PHASE1_IMPLEMENTATION.md:9-17
The flow is orchestrated by several components:
DeploymentTracker: A thread-safe, in-memory store for the state of active and recently completed deployments.DeploymentPoller: A background worker that periodically queries Dokku for the status of an active deployment.DeploymentStatusChecker: An infrastructure component that checks the actual state of an app on Dokku using commands likeapps:reportandps:report.
Sources: PHASE1_IMPLEMENTATION.md:23-61
Deployment Flow
This diagram shows how a deployment request is handled, returning immediately to the client while a background poller tracks the actual build status on Dokku.
Sources: PHASE1_IMPLEMENTATION.md:183-205, internal/server-plugins/deployment/infrastructure/deployment_infrastructure.go:106-121
Configuration
The server can be configured through environment variables or a config.yaml file. Environment variables take precedence and are prefixed with DOKKU_MCP_.
Sources: README.md:104-107, README.md:123-127
A typical config.yaml for local development looks like this:
# SSH configuration for local Dokku instance
ssh:
host: "127.0.0.1"
port: 3022
user: "dokku"
key_path: ".ssh/dokku_mcp_test"
# Security configuration
security:
blacklist:
- "destroy"
- "uninstall"
- "remove"
Sources: scripts/setup-dokku-local.sh:82-101
Dependency Injection
The project uses Uber FX, a dependency injection framework for Go. This helps manage the object graph and application lifecycle. Components are defined as fx.Provide in modules, and FX is responsible for constructing them in the correct order. This is particularly visible in how plugins and their dependencies (repositories, services) are wired together.
Sources: PHASE1_IMPLEMENTATION.md:156-181, internal/server-plugins/app/plugin.go:445-455
Conclusion
The Dokku MCP server is built on a robust and scalable architecture that prioritizes separation of concerns, security, and extensibility. Its adherence to Domain-Driven Design principles creates a clear distinction between business logic and infrastructure, while the plugin-based system allows for modular feature development. The sophisticated Dokku API client and asynchronous operation handling provide a reliable and observable bridge to the underlying Dokku instance, making it a powerful tool for AI-driven platform management.
Sources: README.md, PHASE1_IMPLEMENTATION.md