Skip to content

chore: MCP Dockerfile improvements and native Bun runtime#738

Open
phuongvm wants to merge 2 commits into
plastic-labs:mainfrom
phuongvm:pr-692-mcp-docker
Open

chore: MCP Dockerfile improvements and native Bun runtime#738
phuongvm wants to merge 2 commits into
plastic-labs:mainfrom
phuongvm:pr-692-mcp-docker

Conversation

@phuongvm
Copy link
Copy Markdown

@phuongvm phuongvm commented May 29, 2026

Summary

Improves the MCP server Docker setup with better build performance and native Bun runtime.

Key Changes

  • Multi-stage Docker build: Bun builder stage → Node 20 runtime for optimal install speed
  • Native Bun CMD: Replaces npx wrangler dev with bun run run-mocked.ts — bypasses Wrangler's anti-Bun blocker
  • Mock server: run-mocked.ts provides a Cloudflare-free execution path using Bun's plugin system to stub cloudflare:email
  • Tightened .dockerignore: Excludes .wrangler/ directories and node_modules from build context

Files Changed

  • mcp/Dockerfile — multi-stage build, native Bun CMD
  • mcp/run-mocked.ts — Bun mock server with Cloudflare stub
  • mcp/.dockerignore — MCP-specific ignores
  • mcp/package.json / mcp/bun.lock — dependency updates
  • .dockerignore — root-level wrangler exclusions

Split from #692 per maintainer request to separate MCP infrastructure from LLM fallback.

Summary by CodeRabbit

  • Chores
    • Excluded Wrangler-related dirs and node_modules from Docker build contexts
    • Implemented multi-stage Bun-based container build for smaller, deterministic images
    • Added a local mock server runner for development/testing that starts on a configurable port
    • Set package metadata to disable certain browser/Cloudflare polyfills in the package.json

Review Change Stack

- Multi-stage Docker build (Bun builder → Node 20 runtime)
- Non-root user for security (Trivy DS-0002)
- Native Bun runtime instead of wrangler dev in CMD
- Tightened .dockerignore (root + mcp/)
- Bun mock server (run-mocked.ts) for testing

Fixes security and deployment anti-patterns in MCP container.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 29, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0793597c-1d0d-49b4-80ad-2c8ab07aa908

📥 Commits

Reviewing files that changed from the base of the PR and between 80a1e5c and c29f603.

📒 Files selected for processing (2)
  • mcp/Dockerfile
  • mcp/run-mocked.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • mcp/run-mocked.ts

Walkthrough

Adds Bun-based containerization and runtime for a mock MCP server: Dockerfile and dockerignore updates, a browser package.json block, and mcp/run-mocked.ts which stubs cloudflare:email, loads the MCP module, validates port config, and starts Bun.serve.

Changes

Mock MCP Server Containerization

Layer / File(s) Summary
Docker build and context filters
mcp/Dockerfile, .dockerignore, mcp/.dockerignore
Adds a multi-stage Bun builder/runtime Dockerfile and updates root and mcp-level .dockerignore to exclude .wrangler directories and mcp/node_modules from the build context.
Bun runtime entrypoint and package config
mcp/run-mocked.ts, mcp/package.json
Adds run-mocked.ts which registers a Bun plugin to stub cloudflare:email, dynamically imports ./src/index.ts, validates HONCHO_MCP_PORT (default 8787), and starts Bun.serve. package.json gains a browser block disabling specific polyfills.

Sequence Diagram

sequenceDiagram
  participant Docker as Docker runtime
  participant Bun as Bun runtime (entrypoint)
  participant Plugin as cloudflare-mock plugin
  participant MCP as ./src/index.ts module
  participant HTTP as Bun.serve HTTP server

  Docker->>Bun: start container (CMD bun run run-mocked.ts)
  Bun->>Plugin: register cloudflare-mock plugin
  Bun->>MCP: dynamic import ./src/index.ts
  MCP-->>Bun: export default.fetch handler
  Bun->>HTTP: Bun.serve(start on HONCHO_MCP_PORT, handler = fetch)
  HTTP->>HTTP: serve requests using MCP fetch handler
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A bun in the box, a mock server to run,
I stubbed out the emails and started some fun.
Ports checked and set, the container takes flight,
MCP hops awake in the soft morning light. 🥕✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: Docker improvements (multi-stage build, .dockerignore updates) and native Bun runtime (run-mocked.ts with Bun plugin system).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
mcp/run-mocked.ts (1)

25-25: 💤 Low value

Type assertion bypasses safety checks.

Using as any disables TypeScript's type checking. If module.default.fetch doesn't match Bun.serve's expected signature, errors will only surface at runtime.

♻️ Proposed improvement: Add proper type guard
+  if (typeof module.default?.fetch !== 'function') {
+    throw new Error('MCP module does not export a fetch handler');
+  }
   Bun.serve({
-    fetch: module.default.fetch as any,
+    fetch: module.default.fetch,
     port: port,
   });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mcp/run-mocked.ts` at line 25, Replace the unsafe "as any" on
module.default.fetch with a runtime type guard and safe wrapper: add a small
type-guard function (e.g., isFetchHandler) that checks module.default.fetch is a
function and accepts a Request (or returns a Response/Promise<Response>), then
assign fetch using that guard (e.g., const fetch =
isFetchHandler(module.default.fetch) ? module.default.fetch : (() => { throw new
Error("module.default.fetch has incompatible signature"); })); reference the
property module.default.fetch and the assigned fetch used for Bun.serve so the
code fails early with a clear error instead of bypassing TypeScript checks.
.dockerignore (1)

15-17: 💤 Low value

Redundant pattern: mcp/.wrangler is already matched by **/.wrangler.

Line 16's glob pattern **/.wrangler matches .wrangler in any subdirectory, making line 17's mcp/.wrangler redundant.

♻️ Proposed simplification
 .wrangler
 **/.wrangler
-mcp/.wrangler
 mcp/node_modules
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.dockerignore around lines 15 - 17, The .dockerignore contains a redundant
pattern: the glob "**/.wrangler" already matches ".wrangler" in any subdirectory
so the explicit "mcp/.wrangler" entry should be removed; update the file by
deleting the "mcp/.wrangler" line and keep only the general "**/.wrangler" (and
the top-level ".wrangler" if intended) to avoid duplication.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@mcp/Dockerfile`:
- Around line 13-23: The runtime stage currently uses FROM node:20 but then
invokes bun in CMD ["bun","run","run-mocked.ts"], causing a missing-binary
failure; update the runtime stage base image to a Bun-enabled image (e.g., use
the same Bun-based builder image or an oven/bun image) so the Bun binary is
present, keeping WORKDIR /app and the COPY --from=builder /app /app and leaving
CMD unchanged.
- Around line 1-23: The Dockerfile currently runs the container as root; create
a non-root user and switch to it before CMD to satisfy Trivy DS-0002: add steps
in the Dockerfile to create a user/group (e.g., adduser or groupadd/useradd like
"appuser"), chown /app (the copied files from builder) to that user so Bun can
access files, set USER to that non-root user (place USER appuser just before CMD
["bun","run","run-mocked.ts"]), and ensure any directories that need write
access (e.g., /app, /tmp if used) have appropriate ownership/permissions so the
container runs without root privileges.
- Around line 6-7: The Dockerfile currently copies only package.json before
running RUN bun install, causing non-deterministic installs; modify the COPY
instruction(s) so the bun.lock (or bun.lockb) is copied into the image prior to
RUN bun install (e.g., COPY package.json bun.lock ./ or a separate COPY bun.lock
./) so bun can use the lockfile for deterministic dependency resolution; ensure
the COPY lines preceding RUN bun install are updated accordingly.

In `@mcp/run-mocked.ts`:
- Line 23: The port assignment using Number(process.env.HONCHO_MCP_PORT) can
produce NaN for non-numeric values; validate and normalize the environment value
before passing it to Bun.serve by parsing the string (e.g., parseInt) and
checking Number.isFinite/Number.isInteger and that the value is within the valid
TCP port range (1–65535), then fall back to the default 8787 if validation
fails; update the code that sets the port (the port constant using
process.env.HONCHO_MCP_PORT) so Bun.serve always receives a valid numeric port.

---

Nitpick comments:
In @.dockerignore:
- Around line 15-17: The .dockerignore contains a redundant pattern: the glob
"**/.wrangler" already matches ".wrangler" in any subdirectory so the explicit
"mcp/.wrangler" entry should be removed; update the file by deleting the
"mcp/.wrangler" line and keep only the general "**/.wrangler" (and the top-level
".wrangler" if intended) to avoid duplication.

In `@mcp/run-mocked.ts`:
- Line 25: Replace the unsafe "as any" on module.default.fetch with a runtime
type guard and safe wrapper: add a small type-guard function (e.g.,
isFetchHandler) that checks module.default.fetch is a function and accepts a
Request (or returns a Response/Promise<Response>), then assign fetch using that
guard (e.g., const fetch = isFetchHandler(module.default.fetch) ?
module.default.fetch : (() => { throw new Error("module.default.fetch has
incompatible signature"); })); reference the property module.default.fetch and
the assigned fetch used for Bun.serve so the code fails early with a clear error
instead of bypassing TypeScript checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e16597fa-090c-4e9a-a378-164afe7d4823

📥 Commits

Reviewing files that changed from the base of the PR and between 85239a6 and 80a1e5c.

⛔ Files ignored due to path filters (1)
  • mcp/bun.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • .dockerignore
  • mcp/.dockerignore
  • mcp/Dockerfile
  • mcp/package.json
  • mcp/run-mocked.ts

Comment thread mcp/Dockerfile
Comment thread mcp/Dockerfile Outdated
Comment thread mcp/Dockerfile Outdated
Comment thread mcp/run-mocked.ts Outdated
- Add bun.lock copy before bun install for deterministic builds (Dockerfile)
- Use frozen-lockfile for reproducible installs (Dockerfile)
- Change stage 2 base from node:20 to oven/bun:1 (CMD requires bun binary)
- Run container as non-root USER bun (Dockerfile)
- Validate HONCHO_MCP_PORT to prevent NaN port (run-mocked.ts)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants