feat: eliminate redundant bunx usage with BUN_BE_BUN support#3
feat: eliminate redundant bunx usage with BUN_BE_BUN support#3
Conversation
- Move @modelcontextprotocol/sdk and zod to devDependencies as they are bundled - Remove unnecessary peerDependencies and engines sections - Update description to better reflect tool control functionality - Add author field 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Eliminates redundant bunx usage by leveraging Bun's BUN_BE_BUN=1 environment variable to make the compiled executable behave like bunx. This allows clean usage patterns: - bunx mcp-controller @some/mcp-server (instead of bunx mcp-controller bunx @some/mcp-server) - Works with any npm package, Docker command, or CLI tool - Maintains backward compatibility with existing commands Changes: - Modified target-server.ts to use process.execPath with "x" command and BUN_BE_BUN=1 - Added automatic stripping of bunx/npx prefixes to avoid redundancy - Added integration test with real npm package @modelcontextprotocol/server-sequential-thinking - Updated README with npm package usage example - Added comprehensive design documentation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Pull Request Overview
This PR implements BUN_BE_BUN functionality to eliminate redundant bunx usage when running MCP servers, transforming the user experience from bunx mcp-controller bunx server to bunx mcp-controller server.
- Leverages Bun's native
BUN_BE_BUN=1environment variable for direct npm package execution - Adds comprehensive integration testing with real npm packages
- Optimizes package dependencies by moving MCP SDK and Zod to devDependencies
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/target-server.ts | Implements BUN_BE_BUN mechanism to eliminate redundant bunx calls |
| tests/bunx-integration.test.ts | Adds integration test with real npm package to validate BUN_BE_BUN functionality |
| package.json | Optimizes dependencies and updates package metadata |
| docs/bunx-elimination-design.md | Documents the design rationale and implementation approach |
| README.md | Adds usage example for npm-distributed MCP servers |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
|
|
||
| const [command, ...args] = config.targetCommand; | ||
|
|
||
| const process = Bun.spawn([command, ...args], { | ||
| // Strip bunx/npx prefixes to avoid redundant calls |
There was a problem hiding this comment.
This logic incorrectly handles the case when args is empty. If command is 'bunx' or 'npx' but args is empty, targetCommand will be an empty array, leading to an invalid spawn call. Should check args.length before destructuring.
| // Give the proxy time to start and install the npm package | ||
| await new Promise(resolve => setTimeout(resolve, 3000)); | ||
|
|
There was a problem hiding this comment.
[nitpick] Hard-coded 3-second timeout may be insufficient for slower systems or network conditions. Consider making this configurable or using a more robust waiting mechanism that checks for process readiness.
| // Give the proxy time to start and install the npm package | |
| await new Promise(resolve => setTimeout(resolve, 3000)); | |
| // Wait for the proxy process to be ready by reading the first line of stdout (with timeout) | |
| async function waitForProcessReady(stream, timeoutMs = 10000) { | |
| const reader = stream.getReader(); | |
| const decoder = new TextDecoder(); | |
| let ready = false; | |
| let value; | |
| const start = Date.now(); | |
| while (Date.now() - start < timeoutMs) { | |
| const { value: chunk, done } = await Promise.race([ | |
| reader.read(), | |
| new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout waiting for process readiness')), 1000)) | |
| ]); | |
| if (done) break; | |
| if (chunk) { | |
| value = chunk; | |
| ready = true; | |
| break; | |
| } | |
| } | |
| reader.releaseLock(); | |
| if (!ready) throw new Error('Process did not become ready in time'); | |
| return value; | |
| } | |
| // Wait for process to emit first stdout (as readiness signal) | |
| if (!proxyProcess.stdout || typeof proxyProcess.stdout === 'number') { | |
| throw new Error('Process stdout is not available'); | |
| } | |
| await waitForProcessReady(proxyProcess.stdout); |
Summary
bunxusage when running MCP serversbunx mcp-controller bunx servertobunx mcp-controller serverBUN_BE_BUN=1environment variable for direct npm package executionChanges
Core Implementation
src/target-server.ts: Complete rewrite of target server spawning logicprocess.execPathwith "x" command andBUN_BE_BUN=1environment variablebunx/npxprefixes from command arguments to prevent double-wrappingPackage Optimization
package.json: Optimized dependency structure and metadataDocumentation & Design
README.md: Added clear usage example for npm-distributed MCP serversdocs/bunx-elimination-design.md: Comprehensive design document explaining:Test Coverage
tests/bunx-integration.test.ts: Real-world integration test@modelcontextprotocol/server-sequential-thinking)Technical Benefits
User Experience
bunx mcp-controller serverinstead ofbunx mcp-controller bunx serverPerformance & Reliability
Implementation Quality
Usage Examples
Implementation Details
BUN_BE_BUN Mechanism
BUN_BE_BUN=1environment variable to make compiled executable act likebunCLIprocess.execPathwith "x" command to replicatebunxbehaviorbunx/npxprefixes to prevent double executionCompatibility Strategy
bunxornpxprefixesTest Plan
@modelcontextprotocol/server-sequential-thinking)🤖 Generated with Claude Code
Co-Authored-By: Claude noreply@anthropic.com