-
Notifications
You must be signed in to change notification settings - Fork 614
增加e2b沙盒支持 Feature/add e2b support #531
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
Conversation
WalkthroughThis update introduces support for executing Python code in a secure cloud sandbox (E2B) for the "powerpack" in-memory server type. It adds configuration options in the UI, backend integration with E2B, new localization strings in multiple languages, and updates event dispatching to use a unified method targeting all windows. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI (mcpServerForm.vue)
participant Main Process
participant PowerpackServer
participant E2BManager
participant E2B Cloud
User->>UI (mcpServerForm.vue): Selects powerpack server and enables E2B
UI (mcpServerForm.vue)->>Main Process: Submits config with USE_E2B and E2B_API_KEY
Main Process->>PowerpackServer: Starts server with E2B config
PowerpackServer->>E2BManager: Initialize with API key (if USE_E2B)
E2BManager->>E2B Cloud: Authenticate and prepare sandbox
User->>UI (mcpServerForm.vue): Sends Python code execution request
UI (mcpServerForm.vue)->>PowerpackServer: Request run_code tool
PowerpackServer->>E2BManager: Create sandbox and execute code
E2BManager->>E2B Cloud: Run Python code
E2B Cloud-->>E2BManager: Return output/results
E2BManager-->>PowerpackServer: Return output
PowerpackServer-->>UI (mcpServerForm.vue): Return results to user
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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: 3
🔭 Outside diff range comments (1)
src/renderer/src/components/mcp-config/mcpServerForm.vue (1)
922-934: Hiding the genericenveditor for Powerpack may block advanced usersFor
powerpackservers the standard env textarea is completely hidden.
Users can no longer tweak unrelated variables (e.g.HTTP_PROXY) without switching to JSON import.Recommend leaving the textarea visible (perhaps collapsed) or adding an “advanced” toggle so users still have full control.
♻️ Duplicate comments (1)
src/main/presenter/mcpPresenter/mcpClient.ts (1)
567-570: Replicate the above fix for the failure branchWhen the connection fails you emit the stopped status with the same argument order.
If the order needs swapping (see previous comment) remember to adjust here as well to keep behaviour symmetrical.
🧹 Nitpick comments (19)
src/main/presenter/mcpPresenter/index.ts (1)
384-386: Possible duplicateSERVER_STOPPEDeventIf
stopServer()succeeds it already callseventBus.send(MCP_EVENTS.SERVER_STOPPED …).
When the subsequentstartServer()fails, this extrasendemits the same event twice.Not harmful, but listeners doing state transitions or analytics could double-count.
Wrap the second send with a guard:- eventBus.send(MCP_EVENTS.SERVER_STOPPED, SendTarget.ALL_WINDOWS, serverName) + if (!this.serverManager.isServerRunning(serverName)) { + eventBus.send(MCP_EVENTS.SERVER_STOPPED, SendTarget.ALL_WINDOWS, serverName) + }src/main/presenter/configPresenter/mcpConfHelper.ts (1)
249-255: Broadcast OK – but consider debouncing CONFIG_CHANGEDEvery write to ElectronStore now emits
CONFIG_CHANGEDimmediately. Bulk edits (e.g. import JSON) trigger many rapid sends and can flood renderer IPC.Add a short debounce/throttle around
eventBus.sendinside setters (setMcpServers,add/remove/toggle…) to coalesce updates.No functional bug, just performance polish.
src/renderer/src/i18n/ja-JP/settings.json (1)
380-386: Minor JP localisation fixesTypo & consistency:
-"useE2B": "E2Bサンドボックスを有効にします", -"e2bDescription": "E2Bサンドボックスを使用してPythonコードを実行します", -"e2bApiKey": "E2B Apikey", -"e2bApiKeyPlaceholder": "e2b_1111xx *******など、E2B APIキーをこちらから入力してください。", -"e2bApiKeyHelp": "e2b.devにアクセスして、アピケイを取得します", -"e2bApiKeyRequired": "E2B関数を有効にするには、Apikeyを入力する必要があります" +"useE2B": "E2Bサンドボックスを有効化", +"e2bDescription": "E2Bサンドボックスで Python コードを実行します", +"e2bApiKey": "E2B APIキー", +"e2bApiKeyPlaceholder": "例: e2b_************", +"e2bApiKeyHelp": "e2b.dev で APIキーを取得してください", +"e2bApiKeyRequired": "E2B を有効にするには APIキーが必要です"(“Apikey”→“APIキー”, “アピケイ” typo).
src/main/presenter/mcpPresenter/mcpClient.ts (1)
6-6: Unused named importSendTargetbefore first usage
SendTargetis imported here, but the first usage is ~530 lines later.
Consider re-ordering the import list alphabetically or grouping by package to avoid large temporal gaps between declaration and usage.
(This is only a style/readability concern; feel free to ignore if your code-style rules already allow this.)src/renderer/src/i18n/en-US/settings.json (1)
388-395: Terminology consistency:API keyvsApiKeyAcross the English locale file the phrase is always written as “API Key” (e.g. lines 164-166).
The newly added strings use “ApiKey”/“Api Keys”.- "e2bApiKey": "E2B ApiKey", - "e2bApiKeyPlaceholder": "Enter your E2B Api Keys here, such as e2b_1111xx*******", - "e2bApiKeyHelp": "Go to e2b.dev to get your ApiKey", - "e2bApiKeyRequired": "ApiKey must be entered to enable E2B function" + "e2bApiKey": "E2B API Key", + "e2bApiKeyPlaceholder": "Enter your E2B API key here, e.g. e2b_1111xx*******", + "e2bApiKeyHelp": "Visit e2b.dev to obtain your API key", + "e2bApiKeyRequired": "An API key is required to enable the E2B sandbox"src/renderer/src/i18n/zh-CN/settings.json (1)
387-394: 用词统一:ApiKey→API密钥当前新增字段与同文件中 272 行的 “API密钥” 不一致,建议保持统一:
- "useE2B": "启用E2B沙盒", - "e2bDescription": "使用E2B沙盒执行Python代码", - "e2bApiKey": "E2B ApiKey", - "e2bApiKeyPlaceholder": "这里输入你的E2B Api Keys,如 e2b_1111xx*****", - "e2bApiKeyHelp": "前往 e2b.dev 获取你的 ApiKey", - "e2bApiKeyRequired": "启用E2B功能必须要输入 ApiKey" + "useE2B": "启用 E2B 沙盒", + "e2bDescription": "使用 E2B 沙盒执行 Python 代码", + "e2bApiKey": "E2B API 密钥", + "e2bApiKeyPlaceholder": "请输入 E2B API 密钥,例如 e2b_1111xx*****", + "e2bApiKeyHelp": "前往 e2b.dev 获取 API 密钥", + "e2bApiKeyRequired": "启用 E2B 功能必须输入 API 密钥"src/renderer/src/i18n/zh-TW/settings.json (1)
380-387: 統一專有名詞大小寫建議將
ApiKey全文改為「API 金鑰」以符合 272 行等處既有用法;同時微調語句以符合同文件格式。src/renderer/src/i18n/fr-FR/settings.json (1)
380-386: Accent & capitalisation correctionsPour rester cohérent :
- "useE2B": "Activer E2B Sandbox", - "e2bDescription": "Exécuter le code Python à l'aide de Sandbox E2B", - "e2bApiKey": "E2B APIKEY", - "e2bApiKeyPlaceholder": "Entrez ici vos touches API E2B, comme E2B_1111XX *******", - "e2bApiKeyHelp": "Allez sur e2b.dev pour obtenir votre apikey", - "e2bApiKeyRequired": "Apikey doit être entré pour activer la fonction E2B" + "useE2B": "Activer le bac à sable E2B", + "e2bDescription": "Exécuter du code Python via le bac à sable E2B", + "e2bApiKey": "Clé API E2B", + "e2bApiKeyPlaceholder": "Saisissez votre clé API E2B, ex. e2b_1111xx*******", + "e2bApiKeyHelp": "Visitez e2b.dev pour obtenir votre clé API", + "e2bApiKeyRequired": "Une clé API est requise pour activer la fonctionnalité E2B"src/renderer/src/i18n/fa-IR/settings.json (1)
388-394: Key casing is inconsistent with the rest of the fileMost keys follow camelCase starting with a lower-case letter (e.g.
noFoldersSelected).
The newly-added Persian keys start with lower-case excepte2bApiKeywhere the prefixe2bis lower-case andApiKeyis capitalised.
Please align with existing style (e2bApiKey→e2bApiKeyis fine) or change all languages consistently (e.g. stick toe2bApiKey) to avoid lookup mistakes in the UI.src/renderer/src/i18n/zh-HK/settings.json (1)
380-386: Minor translation placeholder typo
e2bApiKeyPlaceholdercurrently reads這裡輸入你的E2B Api Keys,如 e2b_1111xx*****.
- “Keys” plural may confuse users – the backend expects one key.
- Missing space after
E2B.Consider:
在此輸入你的 E2B API Key,例如 e2b_1111xx*****src/renderer/src/i18n/ru-RU/settings.json (1)
380-386: Mixed letter-case in new keys
"e2bApiKey"is lower-camelCase while the help string saysApikey.
For consistency and to help translators reuse keys, use the same casing everywhere (APIKeyorapiKey, but be consistent across all locales).src/renderer/src/components/mcp-config/mcpServerForm.vue (2)
595-600: Watcher leaves stale API key when E2B toggle is clearedWhen a user unchecks “use E2B”,
useE2Bbecomesfalsebute2bApiKeyretains the previous value.
If the form is re-opened later, the key re-appears although E2B is off.Option: automatically clear the key when
useE2Bswitches fromtrue→false.watch(useE2B, checked => { if (!checked) e2bApiKey.value = '' })
283-287: Validation ignores leading/trailing whitespace
isE2BConfigValidonly checks.trim().length > 0in the main form check, but the rule itself returns raw.length.
Callingtrim()here avoids relying on the outer guard and guarantees consistency.- return e2bApiKey.value.trim().length > 0 + return e2bApiKey.value.trim().length > 0src/main/presenter/mcpPresenter/inMemoryServers/powerpackServer.ts (6)
55-67: Tighten the E2B input schema.
languageis accepted as any string but only'python'is supported. Restrict via.literal('python')or an enum to surface invalid requests early.
88-127:apiKeyfield is dead-code.
this.apiKeyis assigned but never read – static analysis already flags it. Either drop the property or pass it toSandbox.create({ apiKey })(if the lib supports) to prevent bit-rot.
137-143:env.USE_E2Bparsing misses common truthy values.You treat only
true/'true'. Consider also'1','yes', etc., or coerce via['true','1','yes'].includes(String(env.USE_E2B).toLowerCase())for robustness.
212-221: Logging path ignores the “Node only” case.When both Bun and E2B are absent but Node exists, the warning message triggers before the later
console.info. Move the “no runtime” branch after E2B/Node/Bun checks to avoid mixed logs.
223-234: Race-condition when multiple calls initialise E2B.
initialize()has a cheap early-exit but two concurrentstartServercalls could both pass theisInitialized()check before either setsinitialized. Guard with a mutex/Promise cache for certainty.
543-566: Return early for unsupported tool when E2B off.You already gate the tool in
ListTools, but defensive checks here are good. Consider returning a specific error code (e.g.,UNSUPPORTED_TOOL) instead of a generic 400-style message to help the front-end distinguish config vs. execution failures.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (16)
package.json(1 hunks)src/main/presenter/configPresenter/mcpConfHelper.ts(1 hunks)src/main/presenter/mcpPresenter/inMemoryServers/builder.ts(1 hunks)src/main/presenter/mcpPresenter/inMemoryServers/powerpackServer.ts(9 hunks)src/main/presenter/mcpPresenter/index.ts(1 hunks)src/main/presenter/mcpPresenter/mcpClient.ts(4 hunks)src/renderer/src/components/mcp-config/mcpServerForm.vue(8 hunks)src/renderer/src/i18n/en-US/settings.json(1 hunks)src/renderer/src/i18n/fa-IR/settings.json(1 hunks)src/renderer/src/i18n/fr-FR/settings.json(1 hunks)src/renderer/src/i18n/ja-JP/settings.json(1 hunks)src/renderer/src/i18n/ko-KR/settings.json(1 hunks)src/renderer/src/i18n/ru-RU/settings.json(1 hunks)src/renderer/src/i18n/zh-CN/settings.json(1 hunks)src/renderer/src/i18n/zh-HK/settings.json(1 hunks)src/renderer/src/i18n/zh-TW/settings.json(1 hunks)
🧰 Additional context used
🪛 GitHub Check: build-check (x64)
src/main/presenter/mcpPresenter/inMemoryServers/powerpackServer.ts
[failure] 92-92:
'apiKey' is declared but its value is never read.
🔇 Additional comments (6)
package.json (1)
55-59: Dependency version should be pinned or ranged more defensively
@e2b/code-interpreteris a network-facing package that ships fast-moving releases.
Using the loose caret range^1.5.1means any future minor bump (e.g. 1.6.x) will be installed automatically and could break the sandbox flow or Electron bundling without warning.- "@e2b/code-interpreter": "^1.5.1", + "@e2b/code-interpreter": "1.5.1",Pinning the exact version keeps build reproducibility; you can upgrade deliberately once release-notes are reviewed.
Consider adding a renovate/dep-update rule instead of relying on semver guarantees.src/main/presenter/mcpPresenter/mcpClient.ts (2)
538-545:eventBus.sendargument order – double-check against the EventBus APIThe new calls use the order
(eventName, SendTarget.ALL_WINDOWS, payload).
If the internal signature is(target, eventName, payload)(very common in pub/sub helpers), these events will silently be lost or mis-routed.Please verify:
// hypothetical definition send(target: SendTarget, eventName: string, payload?: unknown)If that’s the case, swap the first two arguments:
- eventBus.send(MCP_EVENTS.SERVER_STATUS_CHANGED, SendTarget.ALL_WINDOWS, {...}) + eventBus.send(SendTarget.ALL_WINDOWS, MCP_EVENTS.SERVER_STATUS_CHANGED, {...})
589-592: Consistent shutdown status eventGood call emitting a final “stopped” status on explicit
disconnect().
Once the order issue is verified/fixed, this part looks correct.src/renderer/src/i18n/ko-KR/settings.json (1)
380-386: Double-byte vs ASCII underscore
E2B_1111XXin the placeholder contains ASCII underscore; ensure it is not accidentally replaced by a full-width character in some editors, otherwise copy-pasting may fail validation.src/main/presenter/mcpPresenter/inMemoryServers/powerpackServer.ts (2)
14-14: Ensure packaging includes@e2b/code-interpreter.Electron ASAR bundling can drop native/optional deps. Verify this module is declared in
package.json(runtime & dev) and included in the build, otherwise the import will crash at runtime.
432-473: Tool list duplication when E2B disabled & no JS runtime.If
!useE2Band no Bun/Node,run_node_codeis not pushed butrun_python_codeis always added. That is fine; however, the description forrun_node_coderemains in localisation even though the tool may be absent, potentially confusing the UI that lists all strings.
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: 3
♻️ Duplicate comments (2)
src/main/presenter/mcpPresenter/inMemoryServers/powerpackServer.ts (2)
318-327: Still unsafe access tostdout/stderr– same issue flagged previously
result.logs.stdout&stderrare dereferenced without checking they exist or are arrays. This reproduces the crash reported in the earlier review.- if (result.logs.stdout.length > 0) { + if (result.logs?.stdout?.length) { ... - if (result.logs.stderr.length > 0) { + if (result.logs?.stderr?.length) {
292-342: One sandbox per call – heavy cold-start cost
Sandbox.create()is invoked for every request, incurring ~1-2 s cold-start plus billing overhead. Unless you have strong isolation requirements, pooling a single sandbox (with idle-timeout / explicitkill) reduces latency & cost dramatically.
(Flagged in the previous review as well.)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/main/presenter/mcpPresenter/inMemoryServers/powerpackServer.ts(9 hunks)
🧰 Additional context used
🪛 Gitleaks (8.26.0)
src/main/presenter/mcpPresenter/inMemoryServers/powerpackServer.ts
123-123: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build-check (x64)
| case 'run_code': { | ||
| // E2B 代码执行 | ||
| if (!this.useE2B) { | ||
| throw new Error('E2B is not enabled') | ||
| } | ||
|
|
||
| const parsed = E2BRunCodeArgsSchema.safeParse(args) | ||
| if (!parsed.success) { | ||
| throw new Error(`无效的代码参数: ${parsed.error}`) | ||
| } | ||
|
|
||
| const { code } = parsed.data | ||
| const result = await this.executeE2BCode(code) | ||
|
|
||
| return { | ||
| content: [ | ||
| { | ||
| type: 'text', | ||
| text: `代码执行结果 (E2B Sandbox):\n\n${result}` | ||
| } | ||
| ] | ||
| } | ||
| } |
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.
🛠️ Refactor suggestion
run_code handler ignores the language argument & offers no timeout controls
The schema exposes language (default python) yet the handler:
const { code } = parsed.data
const result = await this.executeE2BCode(code)- silently discards
language– misleading for callers. - offers no per-execution timeout; long-running notebooks will block the server.
Consider:
- const { code } = parsed.data
- const result = await this.executeE2BCode(code)
+ const { code, language } = parsed.data
+ if (language !== 'python') {
+ throw new Error(`Unsupported language "${language}". Currently only 'python' is allowed.`)
+ }
+ const result = await this.executeE2BCode(code /*, timeout? */)🤖 Prompt for AI Agents
In src/main/presenter/mcpPresenter/inMemoryServers/powerpackServer.ts lines 480
to 502, the 'run_code' handler parses a 'language' argument but does not use it,
causing confusion, and lacks timeout controls for code execution, risking server
blocking. Update the handler to extract and pass the 'language' parameter to the
executeE2BCode method or equivalent, ensuring the execution respects the
specified language. Additionally, implement a timeout mechanism for the code
execution to prevent long-running tasks from blocking the server, such as using
a timer or cancellation token to abort execution after a set duration.
| let sandbox: Sandbox | null = null | ||
| try { | ||
| sandbox = await Sandbox.create() | ||
| const result = await sandbox.runCode(code) | ||
|
|
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.
API key must be passed to Sandbox.create
Sandbox.create() supports { apiKey }. Omitting it means:
- The call will 401/403 in production.
- Users have no way to override via the UI even though you request it.
- sandbox = await Sandbox.create()
+ sandbox = await Sandbox.create({ apiKey: this.e2bApiKey })📝 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.
| let sandbox: Sandbox | null = null | |
| try { | |
| sandbox = await Sandbox.create() | |
| const result = await sandbox.runCode(code) | |
| let sandbox: Sandbox | null = null | |
| try { | |
| sandbox = await Sandbox.create({ apiKey: this.e2bApiKey }) | |
| const result = await sandbox.runCode(code) |
🤖 Prompt for AI Agents
In src/main/presenter/mcpPresenter/inMemoryServers/powerpackServer.ts around
lines 292 to 296, the call to Sandbox.create() is missing the required apiKey
parameter. To fix this, modify the call to Sandbox.create() to include the
apiKey argument, passing the appropriate API key value so that the sandbox can
authenticate properly and avoid 401/403 errors in production.
Pull Request Description (中文)
你的功能请求是否与某个问题有关?请描述一下。
参考 https://raw.githubusercontent.com/e2b-dev/mcp-server/refs/heads/main/packages/js/src/index.ts 在powerpack增加了 e2b的支持
桌面应用程序的 UI/UX 更改

Summary by CodeRabbit
New Features
Bug Fixes
Localization
Chores