Running an MCP server directly on your machine is probably the easiest way to get started. Install the package, start the process, connect your client, and you're ready. For development and experimentation, there is nothing wrong with that.
The situation becomes less convenient as you add more servers. One might require Node.js, another Python, another a specific system package, and several may need their own environment variables or credentials. Eventually your local machine starts carrying the runtime requirements of every MCP server you want to try.
That made me wonder whether installing MCP servers directly on the host should really be the default beyond development. For many servers, running them in Docker is an interesting alternative.
Running MCP Servers in Docker
Putting an MCP server in a container gives it a defined runtime environment. Its dependencies and runtime versions stay with the container rather than becoming part of the host machine.
This is particularly useful when different MCP servers have completely different requirements. Instead of maintaining all those runtimes locally, each server can bring the environment it expects. The server also becomes something you can start, stop, replace, and recreate without treating the host as part of its installation.
Docker isn't automatically a security boundary, and containerizing an MCP server doesn't solve every operational problem. But from a runtime-management perspective, it gives you a useful unit to work with.
The interesting part starts when you have more than a few of those units.
What Happens When You Have Ten MCP Servers?
One container is easy to manage manually. Ten starts to look different.
You may have MCP servers for source control, databases, documentation, internal APIs, browser automation, and development tooling. Each can have its own image, configuration, credentials, runtime requirements, and lifecycle.
At that point, the question is no longer simply how to run an MCP server. You need to know which servers exist, which ones are running, how they should be configured, how clients reach them, and what happens when one stops.
Docker gives you a way to run the containers, but it doesn't understand the MCP-specific relationship between them. It doesn't know that one container represents a particular MCP server, which clients should use it, or how an MCP request should reach it.
This is where organizing and orchestrating MCP servers becomes a separate problem.
Organizing MCP Servers
Before orchestrating anything, you need some representation of what you are managing. An MCP server has an identity, a way to run, configuration, potentially credentials, and some way for clients to reach it.
Once that information is managed centrally, MCP servers stop looking like unrelated commands running on a machine. They start looking more like infrastructure.
Orchestration is the next step. Something has to translate that information into actions: start a server, stop it, create its container, connect to an existing instance, recover from a failure, or route a client to the right place.
This distinction is useful because Docker only handles part of the problem. Docker understands containers; the layer above it needs to understand MCP servers.
Where Does an MCP Gateway Fit?
Once servers are managed centrally, it becomes inconvenient for every MCP client to know where every individual server is running. A gateway gives clients a common entry point and can route MCP traffic to the appropriate server.
The gateway may also become a natural place for concerns such as identity, authorization, and session handling.
Figure 1: A gateway can gradually become responsible for more than routing MCP requests.
There is a catch. Once you have a central gateway, it is tempting to make it responsible for starting the servers as well. If those servers run in Docker, the gateway now needs access to Docker. If servers require credentials, credential handling can end up there too.
Eventually the gateway isn't only routing MCP traffic. It is also becoming the execution environment.
That can be a reasonable design for a small system, but it isn't the only option.
Separating Management from Execution
Another approach is to separate the component that understands the MCP environment from the component responsible for running it.
The gateway can handle the control side of the system: requests, routing, identity, authorization, and deciding which MCP server should receive an operation. A runner or broker can handle the execution side: starting processes, creating containers, connecting to running servers, and dealing with their lifecycle.
Figure 2: MCP management and execution can be treated as separate responsibilities.
The useful part of this design isn't simply adding another component. It is that the gateway doesn't necessarily need every capability required to execute every MCP server.
Docker is a good example.
Who Should Talk to Docker?
If your MCP infrastructure dynamically creates containers, some component needs access to Docker. Giving that access directly to the gateway is certainly possible, but another design is to keep Docker interaction in the execution layer.
Figure 3: Container management can sit behind the component responsible for MCP routing.
This doesn't mean the execution layer is automatically secure. Docker access can itself be highly privileged, so whichever component receives that capability still needs to be treated accordingly.
The benefit is simply that the network-facing gateway doesn't need Docker access just because some MCP servers happen to run in containers. Each component can receive the capabilities needed for its particular job.
Credentials Have a Similar Problem
The same question appears when MCP servers require credentials. A GitHub MCP server might need a token, while another server might need database or cloud credentials.
The component deciding whether a user can call a tool doesn't necessarily need to be the same component that supplies the runtime credential required by that tool.
Figure 4: Authorization and runtime credential handling can happen at different layers.
How credentials should actually be provided depends on the system. They might be environment variables, mounted files, short-lived credentials, or something else. The useful architectural question comes before choosing a mechanism: which components actually need access to the credential?
Reducing the number of components that need a secret makes the credential path easier to reason about.
From Running MCP to Orchestrating MCP
So, should you run MCP servers on your local PC? For development, probably. It's simple and there is little reason to introduce infrastructure before you need it.
Docker becomes interesting when you want cleaner runtime environments or don't want every MCP server's dependencies installed directly on the host. Once you start running several containerized MCP servers, however, Docker itself is no longer the interesting problem. You need a way to organize those servers, manage their configuration and lifecycle, and route clients to them.
That's the problem I've been exploring with MCPlama: what happens when MCP servers are treated as infrastructure that can be organized and orchestrated rather than as individual commands someone manually keeps running.
The progression is fairly natural: you start by running an MCP server locally, move it into a container when isolation and runtime management become useful, and eventually need an orchestration layer when the number of servers grows.
At that point, the question has changed from “How do I run this MCP server?” to “How do I manage all of them?”
MCPlama is open source: https://github.com/mcplama/mcplama




Top comments (0)