← All articles

Deploying MCP in a Private Network

A platform that ships as a Docker pull from a public registry is not the right shape for every organisation. Sensitive environments need an upgrade path that works without outbound network access, that integrates with the existing Linux package management story, and that produces audit-friendly artefacts. The I-Machine MCP platform ships as Debian packages served from a private APT repository, installed under systemd on the target hosts. This article describes the pipeline.

The artefact

The build produces a family of .deb packages : One for the MCP server itself, one per plugin, and one per auxiliary binary (such as mcp-ws-bridge). Each package is independently versioned, which makes targeted rollback trivial : Downgrading a single plugin is apt install <pkg>=<previous-version>, no full-stack restore needed.

The packaging script (packaging/build_split_debs.sh) lays out the standard Debian filesystem hierarchy under /opt/mcp/ for binaries, plugins, and shared libraries, plus a systemd unit file at /lib/systemd/system/MCPServer.service. The postinst step runs systemctl daemon-reload and resolves the placeholder fields (user, group, install prefix) against the target host.

The systemd unit

The server runs as a long-lived service. The shipped unit declares :

  • Description=MCP Server
  • After=network.target so the WebSocket layer comes up after the network
  • Type=simple
  • The binary path under /opt/mcp/bin/
  • The runtime user and group, substituted at install time

Operators interact with the service the way they interact with every other service on the host : systemctl status, systemctl restart, journalctl -u MCPServer for logs. The platform does not invent its own process supervisor.

The private APT repository

Distribution lives on a single host inside the corporate network, serving signed APT metadata over HTTP. The repository is a plain directory tree :

/opt/apt-repo/
  pool/main/                    # The .deb files
  dists/stable/main/binary-amd64/
    Packages, Packages.gz       # Generated by dpkg-scanpackages
    Release, InRelease          # Signed manifest

Nginx serves the tree statically. The Release and InRelease manifests are signed with a project-owned GPG key ; The public part of that key is exported to mcp-repo.gpg.key and trusted on every machine that consumes the repository. The signing key itself lives on the build machine and never reaches a target host.

The build and publish flow

Three scripts wire the pipeline :

  • build_release.sh builds the codebase in release configuration with the pinned compiler (see Why We Built Our MCP Server in C++26).
  • build_split_debs.sh packages each binary and plugin into its own .deb, with version stamps derived from the release tag.
  • publish_release.sh copies the artefacts into the repository pool/ tree, regenerates the Packages indexes, and re-signs the Release manifest.

A new release on a target host is then a normal Debian sequence : sudo apt update && sudo apt upgrade. Targeted upgrades or downgrades use the per-package version selector. The flow is auditable through the normal APT logs.

What this gives the operations team

The pipeline maps the MCP platform onto a deployment model every Linux operations team already knows. There is no new tool to install on the target host, no new runtime to monitor, no new credential store to integrate. Every step (build, package, publish, install, supervise) uses the canonical Linux primitive for that step. The platform contributes the artefacts ; The OS contributes the distribution and supervision.

For the broader infrastructure context, see Self-Hosted MCP Infrastructure for Enterprise. For the access-control story that runs on top of this deployment, see RBAC and Audit Logging for MCP.

Talk to us about MCP infrastructure for your organisation. Get in touch.