Skip to main content
Glama
run-npm-pack-integration.sh10 kB
#!/usr/bin/env bash # # Integration test for npm package installation. # Builds packages using `npm pack`, installs them in a clean directory, # and verifies the MCP server and sandbox come up correctly. # # This test validates that the packages work correctly when installed from npm # (simulating what happens with `npx -y @prodisco/k8s-mcp`). # set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" ARTIFACT_DIR="${ROOT_DIR}/artifacts/npm-pack-integration" TEST_DIR="${ARTIFACT_DIR}/test-install" SANDBOX_PORT="${SANDBOX_PORT:-50053}" log() { echo "[npm-pack-integration] $*" } cleanup() { set +e log "Cleaning up..." # Kill any processes we started if [ -n "${SANDBOX_PID:-}" ]; then kill "$SANDBOX_PID" 2>/dev/null || true fi if [ -n "${MCP_PID:-}" ]; then kill "$MCP_PID" 2>/dev/null || true fi # Remove test directory if [ -d "$TEST_DIR" ]; then rm -rf "$TEST_DIR" fi } trap cleanup EXIT # Step 1: Setup log "Setting up test environment" rm -rf "$ARTIFACT_DIR" mkdir -p "$TEST_DIR" # Step 2: Build packages (deps first, then sandbox-server, then main package) log "Building packages" cd "$ROOT_DIR" npm run build -w @prodisco/search-libs npm run build -w @prodisco/prometheus-client npm run build -w @prodisco/loki-client npm run proto:generate -w @prodisco/sandbox-server npm run build -w @prodisco/sandbox-server npm run build # Step 2.5: Pack search-libs and prometheus-client (k8s-mcp and sandbox-server depend on them) log "Creating npm pack for @prodisco/search-libs" cd "$ROOT_DIR/packages/search-libs" SEARCH_LIBS_TARBALL=$(npm pack --pack-destination "$ARTIFACT_DIR" 2>/dev/null | tail -1) log "Created: $SEARCH_LIBS_TARBALL" log "Creating npm pack for @prodisco/prometheus-client" cd "$ROOT_DIR/packages/prometheus-client" PROM_TARBALL=$(npm pack --pack-destination "$ARTIFACT_DIR" 2>/dev/null | tail -1) log "Created: $PROM_TARBALL" # Step 3: Pack loki-client log "Creating npm pack for @prodisco/loki-client" cd "$ROOT_DIR/packages/loki-client" LOKI_TARBALL=$(npm pack --pack-destination "$ARTIFACT_DIR" 2>/dev/null | tail -1) log "Created: $LOKI_TARBALL" # Step 4: Pack sandbox-server log "Creating npm pack for @prodisco/sandbox-server" cd "$ROOT_DIR/packages/sandbox-server" SANDBOX_TARBALL=$(npm pack --pack-destination "$ARTIFACT_DIR" 2>/dev/null | tail -1) log "Created: $SANDBOX_TARBALL" # Step 5: Pack k8s-mcp log "Creating npm pack for @prodisco/k8s-mcp" cd "$ROOT_DIR" MCP_TARBALL=$(npm pack --pack-destination "$ARTIFACT_DIR" 2>/dev/null | tail -1) log "Created: $MCP_TARBALL" # Step 6: Initialize test directory and install packages log "Installing packages in clean test directory" cd "$TEST_DIR" npm init -y > /dev/null # Install search-libs first (prometheus-client depends on it) log "Installing search-libs from tarball" npm install "$ARTIFACT_DIR/$SEARCH_LIBS_TARBALL" --save # Install prometheus-client (sandbox-server depends on it) log "Installing prometheus-client from tarball" npm install "$ARTIFACT_DIR/$PROM_TARBALL" --save # Install loki-client first (sandbox-server depends on it) log "Installing loki-client from tarball" npm install "$ARTIFACT_DIR/$LOKI_TARBALL" --save # Install sandbox-server (k8s-mcp depends on it) log "Installing sandbox-server from tarball" npm install "$ARTIFACT_DIR/$SANDBOX_TARBALL" --save # Install k8s-mcp log "Installing k8s-mcp from tarball" npm install "$ARTIFACT_DIR/$MCP_TARBALL" --save # Step 7: Verify package contents log "Verifying package contents" # Check sandbox-server has the critical files SANDBOX_PKG_DIR="$TEST_DIR/node_modules/@prodisco/sandbox-server" if [ ! -f "$SANDBOX_PKG_DIR/dist/client/index.js" ]; then log "ERROR: sandbox-server missing dist/client/index.js" exit 1 fi if [ ! -f "$SANDBOX_PKG_DIR/dist/server/index.js" ]; then log "ERROR: sandbox-server missing dist/server/index.js" exit 1 fi if [ ! -f "$SANDBOX_PKG_DIR/dist/generated/sandbox.js" ]; then log "ERROR: sandbox-server missing dist/generated/sandbox.js" exit 1 fi log " ✓ sandbox-server package structure is correct" # Check k8s-mcp has the critical files MCP_PKG_DIR="$TEST_DIR/node_modules/@prodisco/k8s-mcp" if [ ! -f "$MCP_PKG_DIR/dist/server.js" ]; then log "ERROR: k8s-mcp missing dist/server.js" exit 1 fi log " ✓ k8s-mcp package structure is correct" # Step 8: Test sandbox-server can start (TCP mode) log "Testing sandbox-server startup" cd "$TEST_DIR" # Start sandbox server in background with TCP mode SANDBOX_SOCKET_PATH="/tmp/npm-pack-test-sandbox.sock" \ node node_modules/@prodisco/sandbox-server/dist/server/index.js & SANDBOX_PID=$! # Wait for sandbox to be ready (check socket exists) for i in {1..30}; do if [ -S "/tmp/npm-pack-test-sandbox.sock" ]; then log " ✓ Sandbox server started (socket ready)" break fi if ! kill -0 $SANDBOX_PID 2>/dev/null; then log "ERROR: Sandbox server exited unexpectedly" wait $SANDBOX_PID || true exit 1 fi sleep 0.5 done if [ ! -S "/tmp/npm-pack-test-sandbox.sock" ]; then log "ERROR: Sandbox server socket not ready after 15 seconds" exit 1 fi # Step 9: Test MCP server can start (with sandbox via socket) log "Testing MCP server startup (with sandbox subprocess)" # Kill the standalone sandbox first - MCP will spawn its own kill $SANDBOX_PID 2>/dev/null || true SANDBOX_PID="" rm -f /tmp/npm-pack-test-sandbox.sock # Create a test script that starts MCP and waits for it to be ready cat > "$TEST_DIR/test-mcp-startup.js" << 'EOF' const { spawn } = require('node:child_process'); const path = require('node:path'); const serverPath = path.join(__dirname, 'node_modules/@prodisco/k8s-mcp/dist/server.js'); console.log('Starting MCP server from:', serverPath); const proc = spawn('node', [serverPath], { stdio: ['pipe', 'pipe', 'pipe'], env: { ...process.env, SANDBOX_SOCKET_PATH: '/tmp/npm-pack-test-mcp-sandbox.sock', }, }); let stderr = ''; let foundReady = false; let foundSandboxReady = false; proc.stderr.on('data', (data) => { const text = data.toString(); stderr += text; process.stderr.write(text); if (text.includes('Sandbox gRPC server is ready')) { foundSandboxReady = true; } if (text.includes('ProDisco MCP server ready on stdio')) { foundReady = true; } }); proc.stdout.on('data', (data) => { // MCP uses stdout for JSON-RPC, just drain it }); // Set a timeout const timeout = setTimeout(() => { console.log('\nTimeout waiting for server startup'); console.log('Found sandbox ready:', foundSandboxReady); console.log('Found MCP ready:', foundReady); proc.kill('SIGTERM'); process.exit(foundSandboxReady && foundReady ? 0 : 1); }, 30000); // Check periodically if both are ready const check = setInterval(() => { if (foundSandboxReady && foundReady) { console.log('\n✓ Both sandbox and MCP server started successfully'); clearTimeout(timeout); clearInterval(check); proc.kill('SIGTERM'); process.exit(0); } }, 100); proc.on('error', (err) => { console.error('Failed to start server:', err); process.exit(1); }); proc.on('exit', (code) => { clearTimeout(timeout); clearInterval(check); if (code !== null && code !== 0 && !foundReady) { console.error('Server exited with code:', code); process.exit(1); } }); EOF node "$TEST_DIR/test-mcp-startup.js" MCP_EXIT_CODE=$? if [ $MCP_EXIT_CODE -ne 0 ]; then log "ERROR: MCP server startup test failed" exit 1 fi log " ✓ MCP server started successfully with sandbox subprocess" # Step 10: Test TCP mode with remote sandbox log "Testing MCP server in TCP mode (remote sandbox)" # Start sandbox server first SANDBOX_USE_TCP=true \ SANDBOX_TCP_PORT="$SANDBOX_PORT" \ node "$TEST_DIR/node_modules/@prodisco/sandbox-server/dist/server/index.js" & SANDBOX_PID=$! # Wait for TCP sandbox to be ready sleep 2 if ! kill -0 $SANDBOX_PID 2>/dev/null; then log "ERROR: TCP sandbox server failed to start" exit 1 fi # Create TCP mode test script cat > "$TEST_DIR/test-mcp-tcp.js" << EOF const { spawn } = require('node:child_process'); const path = require('node:path'); const serverPath = path.join(__dirname, 'node_modules/@prodisco/k8s-mcp/dist/server.js'); console.log('Starting MCP server in TCP mode...'); const proc = spawn('node', [serverPath], { stdio: ['pipe', 'pipe', 'pipe'], env: { ...process.env, SANDBOX_USE_TCP: 'true', SANDBOX_TCP_HOST: 'localhost', SANDBOX_TCP_PORT: '${SANDBOX_PORT}', }, }); let stderr = ''; let foundRemoteConnect = false; let foundMcpReady = false; proc.stderr.on('data', (data) => { const text = data.toString(); stderr += text; process.stderr.write(text); if (text.includes('Connecting to remote sandbox server')) { foundRemoteConnect = true; } if (text.includes('Remote sandbox server is ready')) { foundRemoteConnect = true; } if (text.includes('ProDisco MCP server ready on stdio')) { foundMcpReady = true; } }); const timeout = setTimeout(() => { console.log('\\nTimeout waiting for TCP mode startup'); proc.kill('SIGTERM'); process.exit(1); }, 15000); const check = setInterval(() => { if (foundRemoteConnect && foundMcpReady) { console.log('\\n✓ MCP server connected to remote sandbox via TCP'); clearTimeout(timeout); clearInterval(check); proc.kill('SIGTERM'); process.exit(0); } }, 100); proc.on('error', (err) => { console.error('Failed to start:', err); process.exit(1); }); proc.on('exit', (code) => { clearTimeout(timeout); clearInterval(check); if (!foundMcpReady) { process.exit(1); } }); EOF node "$TEST_DIR/test-mcp-tcp.js" TCP_EXIT_CODE=$? # Cleanup TCP sandbox kill $SANDBOX_PID 2>/dev/null || true SANDBOX_PID="" if [ $TCP_EXIT_CODE -ne 0 ]; then log "ERROR: MCP TCP mode test failed" exit 1 fi log " ✓ MCP server TCP mode works correctly" log "" log "=========================================" log " All npm pack integration tests passed!" log "========================================="

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/harche/ProDisco'

If you have feedback or need assistance with the MCP directory API, please join our Discord server