@debugmcp/mcp-debugger
Version:
Run-time step-through debugging for LLM agents.
130 lines (101 loc) • 5.13 kB
Markdown
# Container Proxy Dependency Analysis Report
## Summary
The E2E container test "should reject absolute paths in container mode" is failing because the proxy files have npm dependencies that aren't available in the minimal Alpine Docker container.
## Changes Made and Reverted
### 1. Enhanced Error Reporting (KEPT)
**File**: `src/proxy/proxy-manager.ts`
**Change**: Added `stderrBuffer` to capture stderr output during proxy initialization
**Rationale**: This enhancement made it possible to diagnose the root cause by capturing the actual error messages from the proxy process
### 2. Dependency Replacements (REVERTED)
**Files**:
- `src/proxy/dap-proxy-dependencies.ts`
- `tests/unit/proxy/dap-proxy-dependencies.test.ts`
**Change**: Replaced fs-extra with built-in fs module
**Status**: REVERTED - This was treating symptoms, not the root cause
### 3. Dockerfile Changes (KEPT)
**File**: `Dockerfile`
**Changes**:
- First changed to copy entire `dist/proxy/` directory
- Then changed to copy entire `dist/` directory
**Status**: These changes revealed the deeper issue with npm dependencies
## Root Cause Analysis
### Error Chain
1. Initial error: `Cannot find module '/app/dist/proxy/dap-proxy-entry.js'`
- Fixed by copying entire dist/proxy directory
2. Second error: `Cannot find package 'fs-extra' imported from /app/dist/proxy/dap-proxy-dependencies.js`
- Temporarily "fixed" by replacing fs-extra with fs
3. Third error: `Cannot find package 'winston' imported from /app/dist/utils/logger.js`
- This revealed the pattern - ALL npm dependencies are missing
### The Fundamental Problem
- The main application (`bundle.cjs`) is properly bundled with all dependencies
- The proxy files are:
- NOT bundled - just TypeScript compiled to JavaScript
- Dynamically imported at runtime
- Still contain `import` statements for npm packages
- The Alpine container only has Node.js runtime - no npm packages installed
## Current Container Build Process
### What Gets Copied
```dockerfile
# Current state - copies all compiled files
COPY --from=builder /workspace/dist/ ./dist/
COPY --from=builder /workspace/package.json ./package.json
```
### What's Missing
- No `node_modules` directory
- No npm packages installed in the runtime container
- Proxy files are not bundled with their dependencies
## Identified Proxy Dependencies
### Direct npm Dependencies in Proxy Files
- `fs-extra` - Used in dap-proxy-dependencies.ts for file operations
- `uuid` - Used in proxy-manager.ts for generating unique IDs
- `@vscode/debugprotocol` - Used throughout for DAP protocol types
### Transitive Dependencies via Shared Modules
- `winston` - Used in src/utils/logger.ts (imported by proxy files)
### Built-in Node.js Modules (These work fine)
- `child_process`, `events`, `net`, `path`, `fs`, `readline`, `url`
## Build Process Analysis
### Current Build Pipeline
1. **TypeScript Compilation**: `tsc` compiles all TypeScript files to JavaScript
2. **Main Bundle Creation**: `scripts/bundle.js` creates `dist/bundle.cjs` with all dependencies included
3. **Proxy Files Copying**: `scripts/copy-proxy-files.cjs` copies JavaScript proxy files to dist
4. **Result**: Main app is bundled, proxy files are NOT bundled
### Why Proxy Files Are Separate
- The proxy is spawned as a **separate child process** to handle DAP communication
- It needs to be a standalone JavaScript file that can be executed independently
- Cannot be part of the main bundle because it runs in its own process space
### Container Build Process
```dockerfile
# Build stage compiles and bundles
FROM node:20-slim AS builder
# ... npm install, build, bundle ...
# Runtime stage has minimal setup
FROM python:3.11-alpine
# Only copies dist files, no node_modules
COPY --from=builder /workspace/dist/ ./dist/
```
## Solution Options
### Option 1: Bundle Proxy Separately (RECOMMENDED)
Create a separate bundle for the proxy that includes all its dependencies:
- Add a proxy bundling step to scripts/bundle.js
- Bundle proxy-entry.js with all dependencies into proxy-bundle.js
- Modify proxy-bootstrap.js to load the bundled version
### Option 2: Install Required Packages in Container
Add npm packages to the runtime container:
```dockerfile
RUN npm install --no-save fs-extra winston uuid @vscode/debugprotocol
```
Pros: Simple fix
Cons: Increases container size, defeats purpose of minimal container
### Option 3: Multi-Stage Selective Copy
Copy only the needed node_modules to the runtime container:
```dockerfile
COPY --from=builder /workspace/node_modules/fs-extra ./node_modules/fs-extra
COPY --from=builder /workspace/node_modules/winston ./node_modules/winston
# ... etc
```
## Recommended Solution
**Bundle the proxy files separately** during the build process. This maintains the minimal container philosophy while ensuring all dependencies are available. The proxy bundle would be self-contained and wouldn't require any npm packages at runtime.
Steps:
1. Modify scripts/bundle.js to create a proxy bundle
2. Update proxy-bootstrap.js to load the bundled proxy
3. Test that the bundled proxy works correctly in the container