Skip to content

fix(windows): resolve MCP stdio server crash on Windows#496

Open
6uu1 wants to merge 6 commits into
Chevey339:masterfrom
6uu1:fix/windows-mcp-stdio-support
Open

fix(windows): resolve MCP stdio server crash on Windows#496
6uu1 wants to merge 6 commits into
Chevey339:masterfrom
6uu1:fix/windows-mcp-stdio-support

Conversation

@6uu1
Copy link
Copy Markdown

@6uu1 6uu1 commented Apr 20, 2026

概述

修复在 Windows 平台上添加 MCP stdio 服务器时应用程序崩溃的问题(BEX64 异常)。

Closes #490

问题描述

在 Windows 上添加 MCP stdio 服务器(如 npx -y @e2b/mcp-server)并保存后,应用程序会立即崩溃退出。

崩溃特征:

  • Event Type: BEX64
  • Exception Code: c0000409 (STATUS_STACK_BUFFER_OVERRUN / C++ Fast-Fail)
  • Faulting Module: flutter_windows.dll

原因分析

问题由两个层面的原因导致:

1. 命令执行方式问题

Windows 上 npm 全局包(如 npx)安装为 .cmd 批处理文件。Dart 的 Process.start() 无法直接执行这些文件,导致进程启动失败并触发底层异常。

2. PATH 环境变量问题

Windows GUI 应用程序无法获取完整的用户 PATH 环境变量(相比于终端启动的应用)。当用户通过 npm 安装了 MCP 服务器命令后,Flutter 应用可能无法找到该命令。

修复方案

Commit 1: mcp_client 传输层修复

StdioClientTransport.create() 中增加 Windows 特殊处理:

if (Platform.isWindows) {
  final cmdLower = command.toLowerCase();
  if (cmdLower.endsWith('.cmd') ||
      cmdLower.endsWith('.bat') ||
      command == 'npx' ||
      command == 'npm') {
    executableCommand = 'cmd.exe';
    effectiveArgs = ['/c', command, ...arguments];
  }
}

Commit 2: Provider 层 PATH 解析与命令验证

  • _getSystemPath(): 通过 PowerShell 获取用户 PATH 并合并,解决 GUI 应用缺少 PATH 的问题
  • _validateCommand(): 改进 Windows 命令验证逻辑,正确处理 .cmd/.bat 文件

Commit 3: 图标兼容性修复

lucide_icons_flutter 3.1.x 中不存在 textSelect 图标,替换为 lassoSelect

修改文件

文件 变更说明
dependencies/mcp_client/lib/src/transport/transport.dart Windows 上使用 cmd.exe 包装 .cmd/.bat 文件和 npm 命令
lib/core/providers/mcp_provider.dart Windows PATH 解析与命令验证改进
lib/icons/lucide_adapter.dart 替换缺失的 textSelect 图标

测试环境

  • Windows Server 2025 (Build 26100)
  • Flutter 3.38.7
  • Kelivo 1.1.11+29

测试计划

  • Windows 上添加 npx -y @e2b/mcp-server MCP stdio 服务器,验证不再崩溃
  • Flutter analyze 通过
  • Windows release 构建成功
  • macOS/Linux 平台验证 MCP stdio 功能无回归

验证步骤

  1. 构建并运行 Windows 版本
  2. 进入 MCP 设置页面
  3. 添加新的 MCP stdio 服务器:
    • 命令: npx
    • 参数: -y @e2b/mcp-server
    • 环境变量: E2B_API_KEY=<your_key>
  4. 保存配置,验证应用正常响应且服务器连接成功

6uu1 added 3 commits April 20, 2026 11:52
On Windows, npm packages like npx are installed as .cmd batch files.
Dart's Process.start cannot directly execute these files, causing
crashes when connecting to MCP stdio servers.

This change wraps .cmd/.bat files and known npm commands (npx, npm)
with cmd.exe /c for proper execution on Windows platforms.
- Add Windows support in _getSystemPath() to merge user PATH from
  registry via PowerShell, fixing missing npm paths in GUI apps
- Improve _validateCommand() to properly validate .cmd/.bat files
  and npm commands using cmd.exe on Windows
- This resolves crashes when adding MCP stdio servers like
  `npx -y @e2b/mcp-server` on Windows
The textSelect icon does not exist in lucide_icons_flutter 3.1.x,
causing build errors. Replace with lassoSelect which serves similar
purpose for text selection UI.
@Chevey339
Copy link
Copy Markdown
Owner

lucide图标那个我改了,可以把那个删了

@6uu1
Copy link
Copy Markdown
Author

6uu1 commented Apr 24, 2026

lucide图标那个我改了,可以把那个删了

我去掉了。你看看

@Chevey339
Copy link
Copy Markdown
Owner

High Priority

1. 预检与执行逻辑不一致,存在较严重的回归风险

  • 现状:在 mcp_provider.dart_validateCommand() 中,验证逻辑变成了通过 cmd.exe /c command --version 实际执行一次来做检查。但在真实连接时,只传入了 cmd 而没有注入完整的配置参数(server.args)。
  • 问题:这种“验证”和“运行”的分叉会导致大量合法配置被误判。例如,仓库自有的 stdio 示例支持 python -m ...node server.js 这种“解释器 + 参数”形式;某些 Batch 脚本也必须带参数才能正常退出。当前预检会因为缺少参数或命令自身不支持 --version 标志而被拦截报错,直接阻断正常启动。
  • 建议核心原则是“验证存在性,不验证可运行性;真正运行只发生一次”。
    建议把 _validateCommand() 改回“只做发现性检查”(仅使用 where/which 确认可执行文件存在即可),不要再去实际触发进程;或者在 Transport 层和 Provider 层抽离一个共享的 resolveStdioLaunch(command, args) 函数,保证两边行为永远一致。

2. Windows 命令大小写判断不一致,修复未完全覆盖

  • 现状transport.dart 中对 npx/npm 的特判是大小写敏感的(command == 'npx' || command == 'npm')。但是 UI 侧保存命令时只做了 trim(),并没有归一化大小写。
  • 问题:Windows 系统本身对大小写不敏感。如果用户输入了 NPXNpm,会因为精确匹配失效而落回旧的裸 Process.start() 路径,导致原本想修的崩溃 Bug 依然被触发。
  • 建议:提取一个统一的 Windows 命令判断函数来处理:
    bool _needsCmdWrapper(String command) {
      if (!Platform.isWindows) return false;
      final lower = command.toLowerCase();
      return lower.endsWith('.cmd') || 
             lower.endsWith('.bat') || 
             lower == 'npx' || 
             lower == 'npm';
    }

Medium/Low Priority

3. 移除多余的进程测试开销
如建议 1 所述,如果仅使用 where/which,我们就能确认命令的存在和可执行性。额外叠加 cmd.exe /c command --version 会带来几百毫秒甚至更高的无谓延迟,且容易引发副作用。同时,原代码中将 exitCode == 1 视为成功状态的判定也掩盖了实际错误,建议一并精简。

4. 缓存 _getSystemPath() 的错误状态
目前的缓存机制中,如果 PowerShell 不可用等原因导致获取失败,_cachedSystemPath 仍为 null,导致后续每次添加 MCP 服务器都会重复进行耗时的系统调用。建议增加一个 _systemPathResolved 的 boolean 标记,避免重复重试。

5. 统一使用 defaultTargetPlatform
当前代码混用了 Platform.isWindows (dart:io 层面) 和 defaultTargetPlatform == TargetPlatform.windows (Flutter 层面)。建议在 Flutter 上下文中统一优先使用 defaultTargetPlatform,这能确保在 Widget Test 中方便地通过 debugDefaultTargetPlatformOverride 来模拟多平台行为。

6. 缺少对 uv 等新兴包管理工具的适配

  • 现状:当前 PR 中的特定命令判断主要集中在 Node.js 生态的 npmnpx 上。
  • 问题:目前 Python 生态中 uv / uvx 的使用已经非常普及,许多用户可能会使用 uvx 启动 MCP 服务器。如果在 Windows 下没有将其纳入特判,同样可能会遇到缺少 cmd.exe /c 包装或无法正常执行的问题。
  • 建议:在重构命令判断逻辑(例如前文建议提取的 _needsCmdWrapper 函数)时,建议顺便将 uvuvx 也纳入关注和适配范围,提升对 Python 生态主流工具的兼容性。

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.

[Bug] 桌面端程序意外崩溃 (BEX64, Exception c0000409 in flutter_windows.dll)

2 participants