-
Notifications
You must be signed in to change notification settings - Fork 10
dxt implementation #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…tadata, capabilities, and server command setup for email management.
…ge.json. Enhance dxt configuration with metadata and server command setup for Mailtrap integration.
… execution and error handling.
…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
… clean up code and improve readability.
WalkthroughAdds 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
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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate 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. Comment |
There was a problem hiding this 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
⛔ 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 transientdxt-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.
…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.
There was a problem hiding this 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
📒 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 mappingpackage.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}" }
There was a problem hiding this 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: | |||
|
|||
[](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) |
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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?
There was a problem hiding this 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 formcp-mailtrap
; otherwise instructions will fail.#!/bin/bash jq -r '.bin' package.jsonIf 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
: Preferunknown
overany
for log data.Improves type safety under strict mode without behavior change.
Apply:
- data?: any + data?: unknownAnd 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 beforeprocess.exit(0)
.If available, keep a
server
reference and callawait 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
: Useinteger
for IDs, notnumber
.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
⛔ 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
pluscommand/args
may be redundant. Verify the MCPB spec.Some bundlers use either
entry_point
orcommand
/args
. Keeping both could be ignored or cause ambiguity.If redundant, prefer
entry_point
alone and dropargs
(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.
"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": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
if (level === "info") { | ||
console.log(JSON.stringify(logEntry)); | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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.
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.
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
bin/build-dxt
script for building distributable DXT filesdxt:build
,dxt:sign
,dxt:info
dxt.json
withmanifest.json
for proper DXT manifest format*.dxt
,dxt-build/
)src/tools/sandbox/sendSandboxEmail.ts
that were causing JSON parsing errorssrc/tools/sendEmail/sendEmail.ts
for cleaner error handlingHow to test
npm run dxt:build
ls -la mailtrap-mcp.dxt
npm run build
npm link
npm test
to ensure all 56 tests passecho '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}' | node dist/index.js
npm run dxt:info
Summary by CodeRabbit