Skip to content

Commit 6ab033b

Browse files
committed
feat(satellite): add runtime validation for Node.js and Python dependencies
1 parent ce656e4 commit 6ab033b

File tree

5 files changed

+385
-0
lines changed

5 files changed

+385
-0
lines changed

services/satellite/.env.example

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,10 @@ NSJAIL_TMPFS_SIZE=100M
125125
# Set to 0 to disable idle timeout (processes never sleep)
126126
# Default: 180 seconds (3 minutes)
127127
MCP_PROCESS_IDLE_TIMEOUT_SECONDS=180
128+
129+
# Runtime Validation (optional)
130+
# Set to 'true' to skip system runtime checks at startup (Node.js, Python)
131+
# By default, satellite validates that required runtimes are installed before starting
132+
# Useful for CI/CD pipelines or Docker builds where runtimes are guaranteed
133+
# Default: false (validates Node.js and Python 3 availability)
134+
DEPLOYSTACK_SKIP_RUNTIME_CHECKS=false

services/satellite/Dockerfile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,24 @@ FROM node:24-bookworm-slim
66
RUN useradd -m -d /opt/deploystack -s /bin/bash deploystack
77

88
# Install essential runtime dependencies including gosu for privilege dropping
9+
# Python 3 and UV are required for Python-based MCP servers
910
RUN apt-get update && \
1011
apt-get install -y --no-install-recommends \
1112
ca-certificates \
1213
gosu \
14+
python3 \
15+
python3-pip \
16+
python3-venv \
1317
&& rm -rf /var/lib/apt/lists/*
1418

19+
# Install UV (Python package manager for MCP servers)
20+
# Using pip installation for reliable system-wide access
21+
# This installs both 'uv' and 'uvx' commands to /usr/local/bin
22+
RUN pip3 install --break-system-packages uv && \
23+
which uv && \
24+
which uvx && \
25+
uv --version
26+
1527
# Create mcp-cache base directory with proper ownership
1628
RUN mkdir -p /opt/deploystack/mcp-cache && \
1729
chown -R deploystack:deploystack /opt/deploystack

services/satellite/README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,37 @@ npm start
5151

5252
The satellite service uses environment variables for configuration and automatically manages persistent storage:
5353

54+
## System Requirements
55+
56+
The satellite service requires the following runtimes to be installed on the system:
57+
58+
### Required Runtimes
59+
60+
- **Node.js 18+** - Requires both `node` (to build) and `npm` (to execute/install packages) for spawning MCP servers
61+
- **Python 3.8+** - Requires `python3` (to build) for Python-based MCP servers
62+
- **UV Package Manager** - Requires `uvx` (to start/execute) for Python async MCP servers
63+
64+
### Optional Runtimes
65+
66+
- **python** - Legacy Python symlink (warns if missing, not required)
67+
68+
### Runtime Validation
69+
70+
The satellite automatically validates that required runtimes are installed during startup:
71+
72+
- **PATH-based detection**: Checks if commands are available in your system PATH (same as shell command lookup)
73+
- **Works everywhere**: Finds commands regardless of installation location (Homebrew, custom paths, etc.)
74+
- **Fail-fast**: If required runtimes are missing, satellite exits with a clear error message
75+
- **All commands required**: For Node.js, both `node` AND `npm` must be present. For Python, both `python3` AND `uvx` must be present.
76+
77+
To skip runtime validation (e.g., for CI/CD or Docker builds):
78+
79+
```bash
80+
DEPLOYSTACK_SKIP_RUNTIME_CHECKS=true npm start
81+
```
82+
83+
**Note**: Skipping runtime checks is not recommended. MCP servers will fail at spawn time if runtimes are actually missing.
84+
5485
### Persistent Storage
5586

5687
Satellites maintain registration state across restarts using local file storage:

services/satellite/src/server.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { McpActivityTracker } from './services/mcp-activity-tracker';
2323
import { ToolSearchService } from './services/tool-search-service';
2424
import { OAuthTokenService } from './services/oauth-token-service';
2525
import { SsePingService } from './services/sse-ping-service';
26+
import { validateSystemRuntimes } from './utils/runtime-validator.js';
2627

2728
/**
2829
* Validate registration token format and availability
@@ -154,6 +155,17 @@ export async function createServer() {
154155
validateSatelliteName(satelliteName, tempLogger);
155156
validateRegistrationToken(registrationToken, tempLogger);
156157

158+
// STEP 1.5: Validate system runtimes (Node.js, Python)
159+
tempLogger.info({ operation: 'runtime_validation_start' }, 'Validating system runtimes...');
160+
const skipRuntimeChecks = process.env.DEPLOYSTACK_SKIP_RUNTIME_CHECKS === 'true';
161+
162+
if (skipRuntimeChecks) {
163+
tempLogger.info({ operation: 'runtime_validation_skipped' }, 'Runtime validation skipped (DEPLOYSTACK_SKIP_RUNTIME_CHECKS=true)');
164+
} else {
165+
validateSystemRuntimes(tempLogger);
166+
tempLogger.info({ operation: 'runtime_validation_complete' }, 'System runtime validation passed');
167+
}
168+
157169
const server = fastify({
158170
logger: loggerConfig,
159171
disableRequestLogging: true,

0 commit comments

Comments
 (0)