Feature: Add persistent remote terminal MCP tools
Add terminal_open / terminal_exec / terminal_close so an AI can hold one shell session per Windows host and run a sequence of commands with cwd and environment preserved, instead of the one-shot exec_command. The persistent terminal is a separate full-command write capability gated by McpTerminal (default off) plus McpReadonly=0, with no whitelist and full audit. One device maps to one terminal session via the shared m_TermSessions map; idle sessions are swept after 300s. terminal_exec rejects commands that contain & or | (they corrupt the sentinel control-operator chain) as well as control characters. Also harden exec_command and terminal_exec against newline/CR injection, fix a dangling subCtx after an abrupt shell disconnect, and refresh lastActiveAt on command completion. Add en/zh-TW translations for the new UI strings and a design document covering both exec_command and the persistent terminal. Co-Authored-By: deepseek-v4-pro
This commit is contained in:
@@ -2193,6 +2193,8 @@ BOOL CMy2015RemoteDlg::OnInitDialog()
|
||||
// 安全配置:只读默认 1(exec_command 默认禁用);白名单空则用内置只读前缀。
|
||||
McpServer().SetReadonly(THIS_CFG.GetInt("settings", "McpReadonly", 1) != 0);
|
||||
McpServer().SetCmdWhitelist(THIS_CFG.GetStr("settings", "McpCmdWhitelist", ""));
|
||||
// 持久终端开关:默认关;要求只读关(McpReadonly=0)才生效(工具列表/分派双重门控)。
|
||||
McpServer().SetTerminalEnabled(THIS_CFG.GetInt("settings", "McpTerminal", 0) != 0);
|
||||
if (!McpServer().Start(mcpBind, mcpPort)) {
|
||||
Mprintf("McpServer start failed on %s:%d\n", mcpBind.c_str(), mcpPort);
|
||||
} else {
|
||||
@@ -5158,6 +5160,12 @@ BOOL CALLBACK CMy2015RemoteDlg::OfflineProc(CONTEXT_OBJECT* ContextObject)
|
||||
WebService().OnTerminalClosed(ContextObject);
|
||||
}
|
||||
|
||||
// MCP 终端(一次性 exec / 持久终端)的 shell 子上下文断开:同步清理会话,避免悬空 subCtx
|
||||
// 被连接池复用时误路由新连接(与 WebService 清理同理,需在 RemoveFromHostList 之前)。
|
||||
if (McpServer().IsRunning() && McpServer().IsTerminalContext(ContextObject)) {
|
||||
McpServer().OnTerminalClosed(ContextObject);
|
||||
}
|
||||
|
||||
SOCKET nSocket = ContextObject->sClientSocket;
|
||||
|
||||
CDialogBase* p = (CDialogBase*)ContextObject->hDlg;
|
||||
|
||||
Reference in New Issue
Block a user