Overview
GitHub deployments allow teams to run MCP servers from private or public repositories. The satellite handles the full lifecycle: downloading the repository, installing dependencies, building the project, and executing the resulting artifacts. Key Benefits:- Deploy private MCP servers without package registry publishing
- Use specific commits or branches for version control
- Full build pipeline with sandboxed execution
Deployment Flow
The deployment process follows these steps:- Config Detection: Satellite identifies GitHub deployments via
source: 'github'and command (npx/uvx) - Token Fetch: Satellite fetches GitHub App installation token from backend
- Download: Repository tarball downloaded via Octokit API
- Extract: Tarball extracted to deployment directory:
- Production: tmpfs at
/opt/mcp-deployments/{team-id}/{installation-id}with 300MB quota - Development: Regular filesystem at
/tmp/mcp-{uuid}(no quota)
- Production: tmpfs at
- Install: Dependencies installed (
npm installoruv sync) - Build: Build script executed if present (
npm run build) - Spawn: Process spawned with transformed config
Runtime Support
Node.js Entry Point Resolution
The satellite resolves Node.js entry points in this order:binfield in package.json (if string or object with matching key)mainfield in package.jsondist/index.jsfallbackindex.jsfallback
Python Installation Patterns
The satellite automatically detects the Python project type and uses the appropriate installation method:Pattern 1: Installable Package
Detection:- Has
pyproject.tomlwith[build-system]section - Has proper package structure (
src/directory OR package directory matching project name) - Has
[project.scripts]or[project.gui-scripts]entries
.venv/bin/{script_name} from [project.scripts]
Example Repository Structure:
Pattern 2: Simple Script with pyproject.toml
Detection:- Has
pyproject.tomlwith dependencies - Lacks
[build-system]OR lacks proper package structure - Has standalone script files at root (
server.py,main.py,app.py, or__main__.py)
.venv/bin/python {script_name}
Example Repository Structure:
Pattern 3: Legacy with requirements.txt
Detection:- Has
requirements.txt - No
pyproject.toml(or pyproject.toml without dependencies)
.venv/bin/python {script_name} or python3 {script_name}
Example Repository Structure:
Python Entry Point Resolution
The satellite resolves Python entry points in this priority order:- Installed script from pyproject.toml:
.venv/bin/{script_name}from[project.scripts] - GUI script from pyproject.toml:
.venv/bin/{script_name}from[project.gui-scripts] - main.py at root:
.venv/bin/python __main__.py(orpython3if no venv) - src/main.py:
.venv/bin/python src/__main__.py - server.py:
.venv/bin/python server.py - main.py:
.venv/bin/python main.py - app.py:
.venv/bin/python app.py - run.py:
.venv/bin/python run.py
services/satellite/src/process/github-deployment.ts - resolvePythonPackageEntry()
Smart Python Version Selection
The satellite automatically selects the best Python version for deployments to maximize wheel compatibility and avoid build failures. Selection Algorithm:- Discovers all available Python 3.x versions on the system (python3.8 through python3.20)
- Identifies bleeding-edge versions (latest minor version with limited wheel support)
- Prefers stable versions with mature package ecosystems
- Falls back gracefully if preferred versions are unavailable
- Current stable version (e.g., 3.13 when 3.14 is bleeding-edge)
- Previous stable version (e.g., 3.12)
- LTS versions (e.g., 3.11, 3.10, 3.9)
- System default (last resort)
pydantic-core and cryptography. This causes build failures when dependencies need source compilation. The smart selector avoids this by preferring stable versions with mature package ecosystems.
Startup Logging:
The satellite logs discovered Python versions at startup:
services/satellite/src/utils/runtime-validator.ts - selectBestPythonForDeployment()
Deployment Directory Lifecycle
GitHub deployments store built artifacts in dedicated directories with different strategies for development and production:Production Mode (Linux)
Directory:/opt/mcp-deployments/{team-id}/{installation-id}
Type: tmpfs (memory-backed filesystem)
Quota: 300MB kernel-enforced hard limit
Benefits:
- Kernel enforces quota - process killed immediately if exceeded
- Memory-backed for faster I/O
- Auto cleanup on reboot
- Proper nsjail mounting as
/app
Development Mode (macOS/Windows/Linux)
Directory:/tmp/mcp-{uuid}
Type: Regular filesystem
Quota: None (for ease of development)
When Directory is Preserved
When Directory is Deleted
Memory Optimization: When a GitHub-deployed process goes dormant due to inactivity, the deployment directory with built artifacts is preserved. This allows respawning in 1-2 seconds instead of 30+ seconds for a full rebuild.
Config Transformation
DuringprepareDeployment(), the config is transformed from package manager command to direct execution.
Before (original config from backend):
Dynamic Args Reconstruction
Why Args Don’t Include SHA
GitHub-deployed MCP servers receive args WITHOUT the commit SHA baked in: Backend Sends:template_argsstored at deployment time would become stale on redeploy- Redeploy updates
git_commit_shacolumn but NOTtemplate_args - Baked SHA would cause old code to run after redeploy
- Dynamic reconstruction ensures latest SHA is always used
Reconstruction Logic
The satellite’sreconstructGitHubArgs() private method combines base args with current SHA:
Safety Checks:
What Gets Reconstructed
Key Insight: Catalog servers from the MCP registry (like sequential-thinking, context7) use static package references (e.g.,
@modelcontextprotocol/server-sequential-thinking) that don’t need SHA reconstruction. Only GitHub-deployed servers (source: 'github') get dynamic reconstruction.
Implementation: services/satellite/src/process/github-deployment.ts - reconstructGitHubArgs()
Logs During Reconstruction:
Redeploy
When users need to deploy updated code from GitHub (new tools, bug fixes, updates), they use the Redeploy feature. What Redeploy Does:- Stops ALL user instances for the installation
- Deletes the shared deployment directory
- Downloads fresh code from GitHub
- Reinstalls dependencies and rebuilds
- Respawns ALL instances with new code
- Initial deployment: 20-60 seconds
- Normal restart: 1-2 seconds (cached)
- Redeploy: 20-60 seconds (fresh download)
Quota and Security
300MB Kernel-Enforced Quota (Production)
GitHub deployments in production use tmpfs with a hard 300MB quota enforced by the Linux kernel. How It Works:- Satellite creates tmpfs:
mount -t tmpfs -o size=300M tmpfs /opt/mcp-deployments/{team}/{install} - Repository extracted to tmpfs
- Dependencies installed (npm/pip) within tmpfs
- If total size exceeds 300MB: Kernel kills the process immediately
- No reactive checks needed - quota is proactive
- Proactive Protection: Process killed before disk exhaustion
- Cannot Be Bypassed: Kernel enforces limit, no userspace workaround
- Fast Failure: Immediate termination vs delayed detection
- Memory-Backed: Faster I/O than disk
- Auto Cleanup: tmpfs freed on reboot even if unmount fails
- Repository files after extraction
node_modules/or Python packages- Build artifacts (
dist/,.venv/) - Any temporary files created during build
- No quota enforced (uses regular
/tmpdirectory) - Allows easier debugging of large dependencies
- Set
MCP_USE_TMPFS=truein.envto test tmpfs behavior locally
Directory Structure
Base Directory:/opt/mcp-deployments/ (created automatically on first deployment)
Per-Deployment Path:
/app (read-only)
Working directory: /app
Entry point: /app/dist/index.js (relative path resolved from /app)
Build Pipeline
Install Phase
Dependencies are installed in a sandboxed environment: Node.js:Build Phase
If a build script is present, it runs after installation: Node.js (ifscripts.build exists in package.json):
Timeout Configuration
Quota Enforcement
In production, all build operations occur within the 300MB tmpfs quota: If Quota Exceeded:- Process killed by kernel during
npm installor build phase - Satellite logs error: “Failed to create deployment tmpfs”
- Installation status set to
failed - tmpfs automatically unmounted
- Large dependency trees (e.g., React app with 1000+ packages)
- Binary dependencies (e.g., native modules)
- Large build artifacts (e.g., bundled assets)
- Optimize dependencies (remove unused packages)
- Use
--productionor--omit=devflags - Pre-build assets before deployment
- Deploy pre-built artifact instead of source
Security
GitHub deployments include multiple security layers to prevent malicious code execution during the build phase.Build Script Validation
The backend validates build scripts before allowing deployment. The satellite re-validates as defense-in-depth. Blocked Patterns:- Network commands (
curl,wget,nc,ssh) - File exfiltration (
scp,rsync,ftp) - Sensitive file access (
/etc/passwd,~/.ssh,~/.aws) - Environment variable dumping (
printenv,env,export)
Sandboxed Builds
Install and build commands run inside nsjail with:- Resource limits (512MB memory, 60s CPU time)
- Restricted filesystem access
- Network policy: allowed for install, blocked for build
- No access to user-provided environment variables
No Secrets in Builds
User-provided environment variables (API keys, tokens) are NOT passed to build commands. This prevents exfiltration via malicious build scripts. Build Environment:Defense-in-Depth
The satellite re-validates scripts before execution, even though the backend already validated them:Error Handling
Download Failures
If repository download fails:- Installation status set to
failed - Error logged with repository details
- Temp directory cleaned up if created
Build Failures
If install or build commands fail:- Installation status set to
failed - Build output captured in logs
- Temp directory preserved for debugging
Missing Entry Point
If no valid entry point is found:- Error thrown with attempted resolution paths
- Installation fails with descriptive error message
Monitoring
Log Events
Debugging
Turn on detailed logging for GitHub deployments:- Repository owner/name/commit
- Temp directory path
- Resolved entry point
- Build command output
Related Documentation
- GitHub Deployment Redeploy - Redeploying with fresh code for all users
- Process Management - Process lifecycle and termination
- Idle Process Management - Dormant state handling
- Instance Lifecycle - Per-user instance management
- MCP Server Security - Build sandboxing and nsjail configuration
- Backend MCP Server Security - First-line build script validation

