Winge-MCP HTTP扩展(MVP)
语言:英语| 简体中文
项目概述
此项目提供了一个最小的C++Winchester扩展DLL,该DLL公开了一个与MCP兼容的HTTP端点(/mcp)和一个基本 windbg.eval 工具。
为什么要使用它
- 通过本地MCP接口运行Winchester命令。
- 将调试器操作集成到MCP客户端和代理工作流中。
- 通过一个小的、轻依赖性的实现来验证Winge+MCP集成。
这是给谁的
- 围绕Windows调试构建MCP工具的工程师。
- 希望执行脚本或代理驱动的Winchester命令的团队。
- 在扩展功能之前需要一个小型参考实现的贡献者。
典型场景
- 执行
windbg.eval从MCP客户端检查寄存器/存储器状态。 - 为Winchester支持的工具构建和测试JSON-RPC路由。
- 验证扩展加载、导出的符号以及Winchester中的请求/响应可见性。
快速开始
先决条件
- 视窗
- CMake 3.20+
- MSVC工具链(Visual Studio构建工具)
- Winchester SDK头文件/libs(
DbgEng.h,dbgeng.lib)
1.构建扩展
cmake -S . -B build -G "Ninja"
cmake --build build预期结果:
- 构建成功。
build/Debug/dbgx-mcp.dll生成。
2.将扩展加载到Winchester中
.load "D:/Repos/Project/AI-Native/dbgx-mcp/build/Debug/dbgx-mcp.dll"预期结果:
.load没有成功Win32 error.- 扩展首先尝试
http://127.0.0.1:5678/mcp. - 中频端口
5678如果端口被占用,它会自动重试后续端口,直到有一个可用。 - Winchester输出始终包含最终监听端点。
重要提示:
- 在中使用正斜杠
.load路径。 - 在调试器命令上下文中,反斜杠可能被视为转义,这可能会导致
Win32 error 0n2. - 对于下面的所有MCP调用,如果发生回退,请使用Winchester日志中显示的最终端口。
3.验证分机是否存在
.chain预期结果:
dbgx-mcp出现在扩展链输出中。
4.发送第一个MCP请求(initialize)
$req = @{
jsonrpc = "2.0"
id = 1
method = "initialize"
params = @{ protocolVersion = "2025-11-25" }
} | ConvertTo-Json -Depth 4
Invoke-RestMethod -Uri "http://127.0.0.1:5678/mcp" -Method Post -ContentType "application/json" -Body $req预期结果:
- 响应包含
jsonrpc,匹配id,以及result.
5.通过MCP运行调试器命令(tools/call)
$req = @{
jsonrpc = "2.0"
id = 2
method = "tools/call"
params = @{
name = "windbg.eval"
arguments = @{ command = "r eax" }
}
} | ConvertTo-Json -Depth 6
Invoke-RestMethod -Uri "http://127.0.0.1:5678/mcp" -Method Post -ContentType "application/json" -Body $req预期结果:
- 响应从Wingey返回命令输出文本。
故障排除 .load 失败
- 确认DLL路径存在并且是绝对路径。
- 验证是否存在所需的导出:
cmake --build build --config Debug --target check_windbg_exports- 在测试流中运行导出检查:
ctest --test-dir build -C Debug --output-on-failure -R verify_windbg_exports- 如果加载仍然失败,请检查相关模块:
dumpbin /dependents build\Debug\dbgx-mcp.dll常见错误:
Win32 error 0n2:错误的路径或路径分隔符解析不正确。Win32 error 0n126:在当前环境中找不到依赖模块。
端口冲突行为:
- 如果启动日志包括
HTTP MCP bind fallback engaged,服务器从默认端口移动到另一个可用端口。 - 使用 `HTTP MCP server listening on http://127.0.0.1:
/mcp` 线作为请求的真相来源。
Winchester调试日志指南
该扩展程序在Winchester输出中为每个对象发出生命周期感知调试日志 /mcp 请求。
关键字段
trace_id:请求相关密钥。用途rpc:当JSON-RPCid存在,否则local-.stage:生命周期阶段(request_received,route_dispatch,tool_execute_start,tool_execute_end,response_sent).duration_ms:自请求开始以来已过去的毫秒数。rpc_method/rpc_id/tool:用于故障排除的核心RPC上下文字段。rpc_outcome:分析结果状态(success,error,unknown).
示例:成功 tools/call
[windbg-mcp] mcp.request method=POST trace_id=rpc:2 stage=request_received duration_ms=0 path=/mcp rpc_method=tools/call rpc_id=2 tool=windbg.eval body_bytes=...
[windbg-mcp] mcp.stage trace_id=rpc:2 stage=route_dispatch duration_ms=0 rpc_method=tools/call rpc_id=2 tool=windbg.eval outcome=in_progress msg=dispatching JSON-RPC request
[windbg-mcp] mcp.stage trace_id=rpc:2 stage=tool_execute_start duration_ms=0 rpc_method=tools/call rpc_id=2 tool=windbg.eval outcome=in_progress msg=entering tool executor
[windbg-mcp] mcp.response status=200 trace_id=rpc:2 stage=tool_execute_end duration_ms=4 has_body=true rpc_id=2 rpc_outcome=success tool=windbg.eval result=...
[windbg-mcp] mcp.response status=200 trace_id=rpc:2 stage=response_sent duration_ms=4 has_body=true rpc_id=2 rpc_outcome=success tool=windbg.eval result=...示例:无效参数失败
[windbg-mcp] mcp.request method=POST trace_id=rpc:3 stage=request_received duration_ms=0 path=/mcp rpc_method=tools/call rpc_id=3 tool=windbg.eval body_bytes=...
[windbg-mcp] mcp.response status=200 trace_id=rpc:3 stage=tool_execute_end duration_ms=1 has_body=true rpc_id=3 rpc_outcome=error tool=windbg.eval error={"code":-32602,...}
[windbg-mcp] mcp.response status=200 trace_id=rpc:3 stage=response_sent duration_ms=1 has_body=true rpc_id=3 rpc_outcome=error tool=windbg.eval error={"code":-32602,...}阻断诊断信号
如果你看到 stage=tool_execute_start 为了一个 trace_id 但从未见过 stage=tool_execute_end 或 stage=response_sent 与相同 trace_id,请求在命令执行过程中停滞(不在HTTP路由中)。
安全行为保持不变:
- 敏感标头被屏蔽(
authorization=). - 长值被截断为
...(truncated).
手动验证检查表(日志可读性)
- 成功路径:
- 发送正常
tools/call(例如r eax). - 验证阶段顺序:
request_received->tool_execute_start->tool_execute_end->response_sent. - 验证
rpc_outcome=success并且始终如一trace_id.
- 故障路径:
- 发送
tools/call没有arguments.command. - 验证响应是否仍然是JSON-RPC错误(
-32602). - 验证日志包括
rpc_outcome=error与匹配trace_id.
- 阻断可观测性路径:
- 发送长时间运行的命令(例如
g)在适当的调试会话中。 - 验证
tool_execute_start在完成之前出现。 - 如果不
tool_execute_end/response_sent出现相同trace_id,诊断为执行阶段停滞。
- 端口回退路径:
- 占据
127.0.0.1:5678在加载扩展之前。 - 加载扩展并验证日志显示绑定回退和非5678最终端口。
- 发送
initialize到达最终港口并验证/mcp是可达的。
MCP请求参考
initialize
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-11-25"
}
}tools/list
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}tools/call (windbg.eval)
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "windbg.eval",
"arguments": {
"command": "r eax"
}
}
}安全说明(MVP)
- 绑定到
127.0.0.1只有。 - 确认
Origin如果存在,只允许http://localhost...和http://127.0.0.1.... - 支持HTTP
POST /mcp对于JSON-RPC。 GET /mcp在这个MVP中返回405(还没有SSE流)。
构建和测试详细信息
运行单元测试:
ctest --test-dir build -C Debug --output-on-failure单元测试策略(MVP):
- 首先测试纯逻辑:JSON解析和JSON-RPC路由。
- 将Winchester和socket操作保存在薄型适配器中。
- 规范中的每个关键行为都映射到至少一个测试。
规范到测试映射
| 规格场景 | 单元测试 |
|---|---|
| 初始化请求成功 | TestInitialize |
| 工具列表请求成功 | TestToolsList |
| 命令执行成功 | TestToolsCallSuccess |
| 缺少命令参数 | TestToolsCallMissingCommand |
| 未知方法被拒绝 | TestUnknownMethod |
| MCP请求摘要包括RPC元数据和屏蔽敏感标头 | TestIoEchoRequestSummaryMasksSensitiveHeader |
| 请求摘要包括跟踪/阶段/工具字段 | TestIoEchoRequestSummaryIncludesTraceContext |
| 从请求元数据中检测到缺少JSON-RPC id | TestIoEchoParseRequestMetaMissingId |
| 本地跟踪id在整个生命周期日志中保持一致 | TestIoEchoLocalTraceIdConsistencyAcrossStages |
| MCP响应摘要涵盖了成功和错误结果 | TestIoEchoResponseSummaryCoversSuccessAndError |
工具结果 isError=true 报告为错误结果 | TestIoEchoResponseSummaryTreatsToolIsErrorAsError |
| 阻塞诊断在响应阶段排序之前使用执行 | TestIoEchoBlockingLocatabilityStageOrder |
| 长MCP摘要用标记截断 | TestIoEchoSummaryTruncatesLongPayload |
| 导出符号检查通过 | verify_windbg_exports |
| 丢失的导出被阻止 | verify_windbg_exports_missing_symbol (WILL_FAIL) |
| 加载命令路径格式可重用 | Load in WinDbg 命令示例 |
| 负载故障具有诊断功能 | Troubleshooting .load failures 部分 |
| JSON处理无效 | TestParseError |
