Skip to content

Conversation

narekhovhannisyan
Copy link
Collaborator

@narekhovhannisyan narekhovhannisyan commented Sep 11, 2025

Motivation

The primary goal was to add DXT (Claude Desktop Extension) support to the Mailtrap MCP server for easier distribution and installation. During development and testing of the DXT functionality, we discovered that the MCP server was experiencing JSON parsing errors in Claude Desktop due to debug console.log statements in the sandbox email functionality. These console.log statements were outputting non-JSON text to stdout, which the MCP server was trying to parse as JSON, causing multiple parsing errors that appeared as error messages in the Claude Desktop interface. This issue needed to be resolved to ensure the DXT extension would work properly.

Changes

  • Added DXT (Claude Desktop Extension) support with new build system and manifest configuration
  • Created bin/build-dxt script for building distributable DXT files
  • Added new npm scripts for DXT operations: dxt:build, dxt:sign, dxt:info
  • Updated package.json with DXT dependencies and scripts
  • Replaced dxt.json with manifest.json for proper DXT manifest format
  • Added DXT build artifacts to .gitignore (*.dxt, dxt-build/)
  • Updated README.md with DXT installation instructions and usage examples
  • Added comprehensive environment variable support in DXT manifest for all required Mailtrap configuration
  • Removed all debug console.log statements from src/tools/sandbox/sendSandboxEmail.ts that were causing JSON parsing errors
  • Removed console.error statement from src/tools/sendEmail/sendEmail.ts for cleaner error handling

How to test

  • Build the DXT file: npm run dxt:build
  • Verify DXT file creation: ls -la mailtrap-mcp.dxt
  • Build the project: npm run build
  • Link the package globally: npm link
  • Update Claude Desktop configuration to use linked version:
    {
      "mcpServers": {
        "mailtrap": {
           "command": "mcp-mailtrap-server",
          "env": {
            "MAILTRAP_API_TOKEN": "your_mailtrap_api_token",
            "DEFAULT_FROM_EMAIL": "your_sender@example.com",
            "MAILTRAP_ACCOUNT_ID": "your_account_id",
            "MAILTRAP_TEST_INBOX_ID": "your_test_inbox_id"
          }
        }
      }
    }
  • Restart Claude Desktop completely (quit and reopen)
  • Verify no JSON parsing errors appear in Claude Desktop interface
  • Test sending a sandbox email through Claude Desktop
  • Test sending a regular email through Claude Desktop
  • Test template management operations (create, list, update, delete)
  • Verify all MCP tools work without console.log interference
  • Run npm test to ensure all 56 tests pass
  • Test MCP server directly with: echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}' | node dist/index.js
  • Test DXT file info: npm run dxt:info
  • Install DXT file in Claude Desktop and verify functionality

Summary by CodeRabbit

  • New Features
    • Added MCP Bundle support with a dedicated server binary and manifest-driven tools.
    • Introduced one-step DXT packaging to produce distributable extensions.
  • Documentation
    • Expanded with MCPB Quick Install, running instructions, error handling, security, logging, troubleshooting, and testing guidance.
  • Refactor
    • Streamlined server startup behind a reusable bootstrap and reduced noisy logs for cleaner output.
  • Scripts
    • New commands for MCPB development, bundle signing, and bundle info.
  • Chores
    • Updated ignore rules to exclude DXT artifacts and temporary build directories.

…tadata, capabilities, and server command setup for email management.
…ge.json. Enhance dxt configuration with metadata and server command setup for Mailtrap integration.
…on approach, streamlining the main function and enhancing server startup process.
…nagement tools. Includes functionality for sending emails, creating, listing, updating, and deleting templates, as well as sandbox email operations.
- Define proper DXT manifest format with dxt_version 0.1
- Configure server entry point to dist/dxt.js
- Set up environment variable mappings for Mailtrap API
- Include metadata: name, version, description, author, license
- Create bin/build-dxt executable script
- Automate TypeScript build process before DXT packaging
- Use @anthropic-ai/dxt pack command to create distributable .dxt file
- Include colored output and progress indicators
- Clean up temporary build directories
- Install @anthropic-ai/dxt as dev dependency for DXT file operations
- Add dxt:build script to run the DXT build process
- Add dxt:sign script for signing DXT files
- Add dxt:info script for inspecting DXT file information
- Update package-lock.json with new dependency
- Add *.dxt pattern to ignore generated DXT files
- Add dxt-build/ directory to ignore temporary build folders
- Prevent accidental commits of build artifacts
- Remove incorrect dxt.json format that was incompatible with DXT pack command
- Replace with proper manifest.json format for DXT toolkit
- Clean up legacy configuration files
- Add Claude Desktop Extension (DXT) section with usage instructions
- Document npm run dxt:build command for creating .dxt files
- Include dxt:sign and dxt:info command documentation
- Explain DXT file distribution and installation process
- Provide clear instructions for users to build and install DXT files
Copy link

coderabbitai bot commented Sep 11, 2025

Walkthrough

Adds MCPB packaging and runtime: new manifest, build/sign scripts, DXT build script, README docs, and ignore rules. Refactors server startup into a reusable server module, adds a dedicated MCPB server entrypoint with structured logging, and removes debug logs from email tools.

Changes

Cohort / File(s) Summary
MCPB packaging & docs
README.md, .gitignore, manifest.json, package.json, bin/build-dxt
Introduces MCPB manifest and tooling, adds DXT build script, new npm scripts (dev/info/sign), dotenv dependency, updated bins, and documentation for install/run/error handling/security/logging/troubleshooting. Adds ignore rules for *.dxt and dxt-build/.
Server bootstrap & entrypoints
src/index.ts, src/server.ts, src/mcpb-server.ts
Extracts server creation/startup into createServer and startServer with stdio transport; simplifies main entry; adds standalone MCPB server with JSON logger, signal handling, and versioned startup.
Log cleanup in tools
src/tools/sandbox/sendSandboxEmail.ts, src/tools/sendEmail/sendEmail.ts
Removes development/debug logging from sandbox sender and error console output from sendEmail catch path; logic unchanged.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User as User/CLI
  participant MCPB as MCPB Server (src/mcpb-server.ts)
  participant Server as McpServer (src/server.ts)
  participant IO as Stdio Transport

  User->>MCPB: Execute mailtrap-mcpb-server
  MCPB->>MCPB: Load env, init Logger
  MCPB->>Server: createServer()
  MCPB->>IO: startServer(server)
  Server-->>IO: Connect via stdio
  MCPB-->>User: Startup logs (JSON)

  rect rgba(200,230,255,0.25)
  Note right of User: Tool invocation (example)
  User->>Server: call tool "send-email" with input
  Server->>Server: Validate input (Zod)
  Server->>Mailtrap: Perform API request
  alt Success
    Server-->>User: Result payload
  else Error/Timeout
    Server-->>User: Error payload (code/message)
  end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Integrate sandbox #32 — Introduces the sendSandboxEmail tool and schema; this PR edits that same implementation by removing debug logs.

Suggested reviewers

  • yanchuk
  • vittorius
  • mklocek
  • VladimirTaytor

Poem

A bundle is packed, with ribbons tight,
I thump my paws—MCPB’s in sight!
Logs hop neatly, JSON bright,
Servers spin on a moonlit night.
No more noisy nibble-chatter—
Quiet queues, that’s rabbit matter. 🐇📦✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title "dxt implementation" is concise and directly reflects the PR's primary intent—adding DXT (Claude Desktop extension) support and related packaging/manifest changes—so it accurately summarizes the main change set (manifest, build script, packaging, README updates, and removal of debug output). It is specific enough for a reviewer scanning history to understand the primary purpose.
Description Check ✅ Passed The PR description follows the repository template by providing a clear Motivation, a detailed Changes list, and a comprehensive How to test checklist that cover DXT support, build/packaging scripts, manifest additions, README updates, and removal of debug logs. There is a small discrepancy to resolve: the description references an npm script "dxt:build" while the package.json summary in the changes mentions "mcpb:sign"/"mcpb:info" and "dev:mcpb" but does not explicitly show "dxt:build", so the author should confirm and align the documented test steps with the actual script names. The Images/GIFs section from the template is not present but is non-critical for functional review.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/dxt-implementation

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

@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: 10

🧹 Nitpick comments (9)
.gitignore (1)

6-7: Consider ignoring signing/inspection byproducts too.

If your DXT flow produces signatures or inspection outputs, add patterns like:

  • *.dxt.sig
  • *.dxt.json (if you export manifest/info alongside)
 *.dxt
+dxt-build/
+*.dxt.sig
+*.dxt.json
-dxt-build/
src/server.ts (1)

78-81: Add graceful shutdown hooks and wrap connection errors with context.

Improve operability and error clarity; also helps tests to await closure.

 export async function startServer(server: McpServer): Promise<void> {
-  const transport = new StdioServerTransport();
-  await server.connect(transport);
+  const transport = new StdioServerTransport();
+  try {
+    await server.connect(transport);
+  } catch (err) {
+    const message = err instanceof Error ? err.message : String(err);
+    throw new Error(`Failed to start MCP server over stdio: ${message}`);
+  }
+  const shutdown = async () => {
+    try {
+      await server.close?.();
+    } finally {
+      process.exit(0);
+    }
+  };
+  process.on("SIGINT", shutdown);
+  process.on("SIGTERM", shutdown);
 }
src/dxt.ts (1)

6-14: Minor: prefer structured error -> message to avoid noisy object dumps.

Keeps stderr cleaner while preserving detail.

-  } catch (error) {
-    console.error("Fatal error:", error);
+  } catch (error) {
+    const msg = error instanceof Error ? error.stack ?? error.message : String(error);
+    console.error("Fatal error:", msg);
     process.exit(1);
   }
src/index.ts (1)

10-13: Console usage in src/

Guidelines forbid console.log; console.error is acceptable for fatal top-level errors, but consider a lightweight logger for consistency.

-  console.error("Fatal error:", error);
+  const msg = error instanceof Error ? error.stack ?? error.message : String(error);
+  console.error("Fatal error:", msg);
README.md (1)

30-46: Add an explicit note on required env vars for DXT installs.

DXT packaging doesn’t remove the need for runtime env (MAILTRAP_API_TOKEN, DEFAULT_FROM_EMAIL, MAILTRAP_ACCOUNT_ID, optional MAILTRAP_TEST_INBOX_ID). Add a short note here and link back to Prerequisites/Setup to prevent confusion.

 This creates a `mailtrap-mcp.dxt` file that you can install directly in Claude Desktop. The DXT file includes all necessary dependencies and can be distributed to users.
+
+> Note
+> The DXT still requires runtime environment variables (MAILTRAP_API_TOKEN, DEFAULT_FROM_EMAIL, MAILTRAP_ACCOUNT_ID, optionally MAILTRAP_TEST_INBOX_ID). See the Prerequisites and Setup sections for details.
bin/build-dxt (3)

1-1: Use env-resolved shebang for portability.

-#!/bin/bash
+#!/usr/bin/env bash

22-27: Version the output artifact to avoid accidental overwrites.

-BUILD_DIR="dxt-build"
-OUTPUT_FILE="mailtrap-mcp.dxt"
+BUILD_DIR="dxt-build"
+VERSION="$(node -p 'require("./package.json").version' 2>/dev/null || echo "local")"
+OUTPUT_FILE="mailtrap-mcp-${VERSION}.dxt"

31-36: Manifest is the source of truth — remove duplicated "dxt" in package.json.

DXT packaging requires a manifest.json; package.json's "dxt" block is optional and will cause drift if duplicated. (npmjs.com)

  • Action: remove the "dxt" block from package.json (or generate manifest.json from it at build time) and update bin/build-dxt (lines 31–36) to stop copying package.json into the DXT build.
package.json (1)

51-51: Use “prepare” instead of “prepublish”.

prepublish runs on install for consumers; prepare is the modern, intended hook for building before publish.

-    "prepublish": "npm run build && shx chmod +x dist/index.js dist/dxt.js",
+    "prepare": "npm run build && shx chmod +x dist/index.js dist/dxt.js",
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between efb4a8a and a341d1b.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • .gitignore (1 hunks)
  • README.md (1 hunks)
  • bin/build-dxt (1 hunks)
  • manifest.json (1 hunks)
  • package.json (3 hunks)
  • src/dxt.ts (1 hunks)
  • src/index.ts (1 hunks)
  • src/server.ts (1 hunks)
  • src/tools/sandbox/sendSandboxEmail.ts (0 hunks)
  • src/tools/sendEmail/sendEmail.ts (0 hunks)
💤 Files with no reviewable changes (2)
  • src/tools/sendEmail/sendEmail.ts
  • src/tools/sandbox/sendSandboxEmail.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts

📄 CodeRabbit inference engine (AGENT.md)

**/*.ts: Use Airbnb TypeScript ESLint config with Prettier formatting
Code must be compatible with TypeScript strict mode targeting ES2022 and CommonJS
Errors should be caught and re-thrown with descriptive messages
Use ES module import syntax and group imports with external modules first
Use camelCase for variables/functions and PascalCase for types/interfaces

Files:

  • src/dxt.ts
  • src/server.ts
  • src/index.ts
src/**/*.ts

📄 CodeRabbit inference engine (AGENT.md)

Do not use console.log in production code; use proper error handling instead

Files:

  • src/dxt.ts
  • src/server.ts
  • src/index.ts
src/index.ts

📄 CodeRabbit inference engine (CLAUDE.md)

src/index.ts is the MCP server entry point and must register all tools and handle the server lifecycle

src/index.ts is the main entry point and must register tools and manage the server lifecycle

Files:

  • src/index.ts
🧠 Learnings (5)
📚 Learning: 2025-09-01T09:54:23.517Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: AGENT.md:0-0
Timestamp: 2025-09-01T09:54:23.517Z
Learning: Applies to src/index.ts : src/index.ts is the main entry point and must register tools and manage the server lifecycle

Applied to files:

  • src/dxt.ts
  • src/server.ts
  • src/index.ts
📚 Learning: 2025-09-01T09:53:45.689Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-01T09:53:45.689Z
Learning: Applies to src/index.ts : src/index.ts is the MCP server entry point and must register all tools and handle the server lifecycle

Applied to files:

  • src/dxt.ts
  • src/server.ts
  • src/index.ts
📚 Learning: 2025-09-01T09:54:23.517Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: AGENT.md:0-0
Timestamp: 2025-09-01T09:54:23.517Z
Learning: MCP server integrates with Mailtrap email service

Applied to files:

  • manifest.json
📚 Learning: 2025-09-01T09:53:45.689Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-01T09:53:45.689Z
Learning: Applies to src/client.ts : src/client.ts must configure and initialize the Mailtrap client

Applied to files:

  • manifest.json
📚 Learning: 2025-09-01T09:54:23.517Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: AGENT.md:0-0
Timestamp: 2025-09-01T09:54:23.517Z
Learning: Applies to src/client.ts : src/client.ts must initialize the Mailtrap API client

Applied to files:

  • manifest.json
🧬 Code graph analysis (2)
src/dxt.ts (1)
src/server.ts (2)
  • createServer (21-76)
  • startServer (78-81)
src/index.ts (1)
src/server.ts (2)
  • createServer (21-76)
  • startServer (78-81)
🔇 Additional comments (7)
.gitignore (1)

6-7: LGTM on ignoring DXT artifacts.

Ignoring generated .dxt bundles and the transient dxt-build/ dir is correct.

src/server.ts (1)

30-35: Tool registration set looks solid and coherent.

Names, descriptions, and schema/handler pairings are consistent and readable.

Also applies to: 40-63, 68-73

manifest.json (2)

1-31: Manifest looks correct and minimal.

Entry, command/args, and env mapping align with a Node-based MCP DXT.


2-5: Validate DXT manifest & produce missing build artifact

  • manifest.json.version == package.json.version == 0.0.3 — OK.
  • dist/dxt.js missing; ensure the build produces dist/dxt.js or update manifest.entry_point to an existing bundle.
  • Confirm dxt_version and manifest structure against the latest DXT spec (can't verify from repo). Specifically confirm whether entry_point and mcp_config must be present together or may be used independently; provide the spec link or update the manifest accordingly.

Also applies to: lines 11-16.

src/index.ts (1)

3-7: Confirm guideline intent: tool registration moved from index.ts to server.ts.

This refactor improves modularity, but coding_guidelines state “src/index.ts must register all tools.” If that’s a hard requirement, either update the guideline or re-export a thin registrar from index.ts.

package.json (2)

56-58: DXT scripts: LGTM and consistent with build-dxt.


67-67: Verify toolchain compatibility (TypeScript / @types/node / @anthropic-ai/dxt).

"@anthropic-ai/dxt": "^0.2.6" (package.json: line 67) — upstream dxt@0.2.6 exists; TypeScript 5.9 and @types/node majors for Node 16/18/20 are available. Confirm dxt@0.2.6 does not require Node 18+ runtime features and that the repository's TypeScript + chosen @types/node major build cleanly under engines.node >=16.20.1: run npm view @anthropic-ai/dxt engines and run CI/local build on Node 16.20.1; if dxt requires Node 18+, either raise engines or add necessary polyfills.

@yanchuk yanchuk requested review from vittorius, yanchuk and VladimirTaytor and removed request for vittorius and VladimirTaytor September 11, 2025 15:30
@narekhovhannisyan narekhovhannisyan self-assigned this Sep 12, 2025
…rt from server.ts

- Import dotenv configuration in index.ts to manage environment variables
- Remove direct dotenv configuration call from server.ts to streamline code
- Include MAILTRAP_ACCOUNT_ID and MAILTRAP_TEST_INBOX_ID in the environment variables for improved email testing setup.
Copy link

@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: 0

♻️ Duplicate comments (2)
src/index.ts (1)

3-4: Env preloaded before server import — good.

This addresses earlier feedback; prevents config from loading late.

package.json (1)

11-14: CLI alias added — matches docs.

Adding “mcp-mailtrap” alongside the existing bin is correct.

🧹 Nitpick comments (1)
package.json (1)

52-52: Use prepublishOnly instead of prepublish.

Avoid running on install; restrict to publish time.

-"prepublish": "npm run build && shx chmod +x dist/index.js dist/dxt.js",
+"prepublishOnly": "npm run build && shx chmod +x dist/index.js dist/dxt.js",
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a341d1b and 03785f3.

📒 Files selected for processing (4)
  • package.json (3 hunks)
  • src/dxt.ts (1 hunks)
  • src/index.ts (1 hunks)
  • src/server.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/server.ts
  • src/dxt.ts
🧰 Additional context used
📓 Path-based instructions (3)
src/index.ts

📄 CodeRabbit inference engine (CLAUDE.md)

src/index.ts is the MCP server entry point and must register all tools and handle the server lifecycle

src/index.ts is the main entry point and must register tools and manage the server lifecycle

Files:

  • src/index.ts
**/*.ts

📄 CodeRabbit inference engine (AGENT.md)

**/*.ts: Use Airbnb TypeScript ESLint config with Prettier formatting
Code must be compatible with TypeScript strict mode targeting ES2022 and CommonJS
Errors should be caught and re-thrown with descriptive messages
Use ES module import syntax and group imports with external modules first
Use camelCase for variables/functions and PascalCase for types/interfaces

Files:

  • src/index.ts
src/**/*.ts

📄 CodeRabbit inference engine (AGENT.md)

Do not use console.log in production code; use proper error handling instead

Files:

  • src/index.ts
🧠 Learnings (7)
📚 Learning: 2025-09-01T09:53:45.689Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-01T09:53:45.689Z
Learning: Applies to src/index.ts : src/index.ts is the MCP server entry point and must register all tools and handle the server lifecycle

Applied to files:

  • src/index.ts
📚 Learning: 2025-09-01T09:54:23.517Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: AGENT.md:0-0
Timestamp: 2025-09-01T09:54:23.517Z
Learning: Applies to src/index.ts : src/index.ts is the main entry point and must register tools and manage the server lifecycle

Applied to files:

  • src/index.ts
📚 Learning: 2025-09-01T09:54:23.517Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: AGENT.md:0-0
Timestamp: 2025-09-01T09:54:23.517Z
Learning: Applies to src/config/index.ts : src/config/index.ts must define server configuration constants

Applied to files:

  • src/index.ts
📚 Learning: 2025-09-01T09:53:45.689Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-01T09:53:45.689Z
Learning: Set and require environment variables MAILTRAP_API_TOKEN (required), DEFAULT_FROM_EMAIL (required), and MAILTRAP_ACCOUNT_ID (optional)

Applied to files:

  • package.json
📚 Learning: 2025-09-01T09:53:45.689Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-01T09:53:45.689Z
Learning: Applies to src/client.ts : src/client.ts must configure and initialize the Mailtrap client

Applied to files:

  • package.json
📚 Learning: 2025-09-01T09:54:23.517Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: AGENT.md:0-0
Timestamp: 2025-09-01T09:54:23.517Z
Learning: Applies to src/client.ts : src/client.ts must initialize the Mailtrap API client

Applied to files:

  • package.json
📚 Learning: 2025-09-01T09:54:23.517Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: AGENT.md:0-0
Timestamp: 2025-09-01T09:54:23.517Z
Learning: MCP server integrates with Mailtrap email service

Applied to files:

  • package.json
🧬 Code graph analysis (1)
src/index.ts (1)
src/server.ts (2)
  • createServer (18-73)
  • startServer (75-78)
🔇 Additional comments (2)
src/index.ts (1)

7-8: Lean bootstrap that delegates to server module — good.

Entry point now just creates and starts the server as required.

package.json (1)

32-36: Add DEFAULT_FROM_EMAIL to DXT env mapping

package.json .dxt.mcpServers.mailtrap.env is missing DEFAULT_FROM_EMAIL; manifest.json .mcpServers.mailtrap.env could not be parsed (jq: null has no keys) — parity not confirmed.

File: package.json (lines 32-36)

         "env": {
           "MAILTRAP_API_TOKEN": "${env:MAILTRAP_API_TOKEN}",
+          "DEFAULT_FROM_EMAIL": "${env:DEFAULT_FROM_EMAIL}",
           "MAILTRAP_ACCOUNT_ID": "${env:MAILTRAP_ACCOUNT_ID}",
           "MAILTRAP_TEST_INBOX_ID": "${env:MAILTRAP_TEST_INBOX_ID}"
         }

Copy link
Contributor

@vittorius vittorius left a comment

Choose a reason for hiding this comment

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

@yanchuk @narekhovhannisyan BTW from Sep 11, 2025, Claude recommends using *.mcpb ("MCP bundle" naming convention for DXT). I think it's better to rename before we released it. See the top of their blog post and their GH repo.

README.md Outdated
@@ -27,7 +27,22 @@ Before using this MCP server, you need to:

[![Install with Node in VS Code](https://img.shields.io/badge/VS_Code-Node-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=mailtrap&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22mcp-mailtrap%22%5D%2C%22env%22%3A%7B%22MAILTRAP_API_TOKEN%22%3A%22%24%7Binput%3AmailtrapApiToken%7D%22%2C%22DEFAULT_FROM_EMAIL%22%3A%22%24%7Binput%3AsenderEmail%7D%22%2C%22MAILTRAP_ACCOUNT_ID%22%3A%22%24%7Binput%3AmailtrapAccountId%7D%22%7D%7D&inputs=%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22mailtrapApiToken%22%2C%22description%22%3A%22Mailtrap+API+Token%22%2C%22password%22%3Atrue%7D%2C%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22senderEmail%22%2C%22description%22%3A%22Sender+Email+Address%22%7D%2C%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22mailtrapAccountId%22%2C%22description%22%3A%22Mailtrap+Account+ID%22%7D%5D)

### Claude Desktop Extension (DXT)
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be great to have a 1-click install link for Claude in the README if it's possible...

Copy link
Contributor

Choose a reason for hiding this comment

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

@narekhovhannisyan can you please address that?

Copy link

@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: 2

♻️ Duplicate comments (1)
README.md (1)

50-64: Ensure CLI name matches package.json bin.

Docs use npx mcp-mailtrap. Confirm a bin alias exists for mcp-mailtrap; otherwise instructions will fail.

#!/bin/bash
jq -r '.bin' package.json

If only mcp-mailtrap-server is present, either add an alias or update README.

🧹 Nitpick comments (8)
src/mcpb-server.ts (3)

73-79: Avoid hard‑coded version; derive at runtime to prevent drift.

Apply:

-    logger.info("Starting Mailtrap MCPB Server", { version: "0.0.3" });
+    const version =
+      process.env.npm_package_version ??
+      process.env.MCPB_VERSION ??
+      "unknown";
+    logger.info("Starting Mailtrap MCPB Server", { version });

24-28: Prefer unknown over any for log data.

Improves type safety under strict mode without behavior change.

Apply:

-    data?: any
+    data?: unknown

And in helpers:

-  info(message: string, data?: any): void {
+  info(message: string, data?: unknown): void {
   ...
-  warn(message: string, data?: any): void {
+  warn(message: string, data?: unknown): void {
   ...
-  error(message: string, data?: any): void {
+  error(message: string, data?: unknown): void {
   ...
-  debug(message: string, data?: any): void {
+  debug(message: string, data?: unknown): void {

Also applies to: 52-66


88-97: Consider graceful shutdown of transport before exit.

If McpServer exposes a close/shutdown, hook it here to flush pending frames before process.exit(0).

If available, keep a server reference and call await server.close?.() on SIGINT/SIGTERM.

README.md (2)

30-42: MCPB vs DXT terminology: clarify scope and cross‑link.

PR title emphasizes DXT, while this section documents MCP Bundles (MCPB). Add a short note explaining both packaging options and how manifest.json serves each, or provide a DXT section alongside MCPB to avoid confusion.


362-381: State explicitly: logs go to stderr only.

Add a note that all runtime logs are emitted on stderr to avoid corrupting the MCP stdio protocol on stdout.

Suggested snippet:

[!NOTE]
For stdio transports, all logs are emitted on stderr. Do not write to stdout, which is reserved for JSON‑RPC frames.

manifest.json (3)

155-157: Use integer for IDs, not number.

Prevents accidental floats in clients and better reflects API expectations.

Apply:

-          "template_id": {
-            "type": "number",
+          "template_id": {
+            "type": "integer",
             "description": "ID of the template to update"
           }

And similarly in delete‑template.

Also applies to: 190-192


100-106: Express “text or html required” in schema.

Runtime will validate, but declare it here to give earlier feedback in hosts.

Apply:

         "required": ["to", "subject", "category"],
+        "oneOf": [
+          { "required": ["text"] },
+          { "required": ["html"] }
+        ],

258-261: DEFAULT_FROM_EMAIL marked optional here but required in README. Align.

Make the requirement consistent across docs and manifest.

Apply one of:

  • Mark as required in setup instructions, or
  • Keep optional but update README’s “Required Environment Variables” to reflect it’s only required when sending.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 03785f3 and 8573524.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • README.md (2 hunks)
  • manifest.json (1 hunks)
  • package.json (3 hunks)
  • src/mcpb-server.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
🧰 Additional context used
📓 Path-based instructions (2)
**/*.ts

📄 CodeRabbit inference engine (AGENT.md)

**/*.ts: Use Airbnb TypeScript ESLint config with Prettier formatting
Code must be compatible with TypeScript strict mode targeting ES2022 and CommonJS
Errors should be caught and re-thrown with descriptive messages
Use ES module import syntax and group imports with external modules first
Use camelCase for variables/functions and PascalCase for types/interfaces

Files:

  • src/mcpb-server.ts
src/**/*.ts

📄 CodeRabbit inference engine (AGENT.md)

Do not use console.log in production code; use proper error handling instead

Files:

  • src/mcpb-server.ts
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-01T09:53:45.689Z
Learning: Applies to src/index.ts : src/index.ts is the MCP server entry point and must register all tools and handle the server lifecycle
📚 Learning: 2025-09-01T09:53:45.689Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-01T09:53:45.689Z
Learning: Applies to src/index.ts : src/index.ts is the MCP server entry point and must register all tools and handle the server lifecycle

Applied to files:

  • src/mcpb-server.ts
📚 Learning: 2025-09-01T09:54:23.517Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: AGENT.md:0-0
Timestamp: 2025-09-01T09:54:23.517Z
Learning: Applies to src/index.ts : src/index.ts is the main entry point and must register tools and manage the server lifecycle

Applied to files:

  • src/mcpb-server.ts
📚 Learning: 2025-09-01T09:53:45.689Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-01T09:53:45.689Z
Learning: Applies to src/client.ts : src/client.ts must configure and initialize the Mailtrap client

Applied to files:

  • src/mcpb-server.ts
  • README.md
📚 Learning: 2025-09-01T09:54:23.517Z
Learnt from: CR
PR: railsware/mailtrap-mcp#0
File: AGENT.md:0-0
Timestamp: 2025-09-01T09:54:23.517Z
Learning: MCP server integrates with Mailtrap email service

Applied to files:

  • src/mcpb-server.ts
  • manifest.json
  • README.md
🧬 Code graph analysis (1)
src/mcpb-server.ts (1)
src/server.ts (2)
  • createServer (18-73)
  • startServer (75-78)
🔇 Additional comments (4)
src/mcpb-server.ts (1)

1-21: Bootstrap structure looks solid.

Shebang, dotenv preload, singleton logger, main‑module guard, and error paths are clean.

Also applies to: 69-86, 99-107

manifest.json (2)

29-33: entry_point plus command/args may be redundant. Verify the MCPB spec.

Some bundlers use either entry_point or command/args. Keeping both could be ignored or cause ambiguity.

If redundant, prefer entry_point alone and drop args (or vice versa) per the packaging tool’s spec.


24-26: Overall manifest structure looks good.

Capabilities, tool coverage, env mapping, and Node requirement are coherent and match server bootstrap.

Consider adding brief examples for tool inputs to improve UX in hosts that surface schema examples.

Also applies to: 41-250

README.md (1)

24-29: Do not add a 1‑click “Install in Claude Desktop” deep‑link — Anthropic documents no install URL scheme.
Anthropic only supports installing from the in‑app Extensions page or by opening/dragging a .dxt file; update the README Quick Install to link to the DXT/.dxt install docs or provide the .dxt file for users to open/drag.

Likely an incorrect or invalid review comment.

Comment on lines +199 to +213
"name": "send-sandbox-email",
"description": "Send email in sandbox mode to a test inbox",
"inputSchema": {
"type": "object",
"properties": {
"from": {
"type": "string",
"format": "email",
"description": "Email address of the sender"
},
"to": {
"type": "string",
"description": "Email addresses (comma-separated or single)"
},
"subject": {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Align sandbox tool schema with docs and send‑email schema.

  • to should accept string OR array of emails (like send‑email).
  • from should be optional (README says default is used).

Apply:

-          "to": {
-            "type": "string",
-            "description": "Email addresses (comma-separated or single)"
-          },
+          "to": {
+            "anyOf": [
+              { "type": "string", "format": "email", "description": "Single email address" },
+              {
+                "type": "array",
+                "items": { "type": "string", "format": "email" },
+                "description": "Array of email addresses"
+              }
+            ],
+            "description": "Email address(es) of the recipient(s) - can be a single email or array of emails"
+          },
...
-        "required": ["from", "to", "subject"],
+        "required": ["to", "subject"],

Also applies to: 246-247

🤖 Prompt for AI Agents
In manifest.json around lines 199-213 (and also adjust the same pattern at lines
246-247), the sandbox tool schema currently requires "from" and limits "to" to a
single string; update the JSON Schema so "from" is optional (remove it from
required or ensure it has no required constraint) and change "to" to accept
either a single string or an array of emails — implement this using oneOf: [{
"type":"string", "format":"email" }, { "type":"array", "items": {
"type":"string", "format":"email" } }] (or equivalent anyOf), and ensure any
references at 246-247 are updated the same way so behavior matches README and
send-email schema.

Comment on lines +42 to +45
if (level === "info") {
console.log(JSON.stringify(logEntry));
return;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

🧩 Analysis chain

Do not write logs to stdout (breaks MCP stdio protocol). Route INFO to stderr.

Stdio transport expects stdout to carry only JSON‑RPC frames. Writing INFO logs to stdout will cause parse errors in hosts (the exact issue this PR set out to fix). Also violates src/**/*.ts guideline “no console.log in production code.”

Apply:

-    if (level === "info") {
-      console.log(JSON.stringify(logEntry));
-      return;
-    }
+    if (level === "info") {
+      // Use stderr to avoid contaminating MCP stdio protocol on stdout
+      console.error(JSON.stringify(logEntry));
+      return;
+    }

Run to ensure no remaining stdout logging:


🏁 Script executed:

#!/bin/bash
rg -n --type=ts 'console\.log\(' src | sed -n '1,200p'

Length of output: 66


Route INFO logs to stderr — do not write to stdout

Stdout must carry only JSON‑RPC frames for the MCP stdio transport; writing INFO to stdout will break parsing. Change the console.log at src/mcpb-server.ts:43 to stderr.

Apply:

-    if (level === "info") {
-      console.log(JSON.stringify(logEntry));
-      return;
-    }
+    if (level === "info") {
+      // Use stderr to avoid contaminating MCP stdio protocol on stdout
+      console.error(JSON.stringify(logEntry));
+      return;
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (level === "info") {
console.log(JSON.stringify(logEntry));
return;
}
if (level === "info") {
// Use stderr to avoid contaminating MCP stdio protocol on stdout
console.error(JSON.stringify(logEntry));
return;
}
🤖 Prompt for AI Agents
In src/mcpb-server.ts around lines 42 to 45, INFO-level log entries are
currently written to stdout via console.log which corrupts the MCP stdio
JSON-RPC stream; change the output to stderr (e.g., use console.error or
process.stderr.write with the JSON string and a newline) so stdout remains
reserved for RPC frames and INFO logs go to stderr.

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.

3 participants