#pragma once #include #include #include #include #include #include #include #include #include #include // httplib 与 Windows 头部的 min/max 宏冲突,按 file_server.h 的既有约定处理。 #undef min #undef max #include "httplib.h" #ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) #endif #ifndef min #define min(a,b) (((a) < (b)) ? (a) : (b)) #endif #pragma comment(lib, "ws2_32.lib") class CMy2015RemoteDlg; // MCP (Model Context Protocol) 服务端:httplib 封装 + JSON-RPC 2.0 分发 + 静态 token 校验。 // 与 CWebService 平级、互不依赖;默认禁用,经「扩展 → MCP设置」开启后监听 // (默认 127.0.0.1:6544,仅本机回环)。见 docs/Mcp_Design.md。 class CMcpServer { public: static CMcpServer& Instance(); void SetParentDlg(CMy2015RemoteDlg* pDlg) { m_parent = pDlg; } void SetToken(const std::string& token) { m_token = token; } bool Start(const std::string& bind, int port); void Stop(); bool IsRunning() const { return m_running.load(); } // ===== P2b:无请求 id 的一次性响应 → 每 host 单飞行 ===== // 进程/窗口列表(TOKEN_PSLIST/TOKEN_WSLIST,一次性子链接)与历史活动 // (TOKEN_REPORT_ACTIVITY,主连接 RPC)都不带请求关联,同一 host 同一时刻 // 只允许一个挂起请求,避免同 host 并发请求响应归属歧义。 // 注意:单飞行只约束 MCP 侧同 host 并发,不约束与 MFC 对话框并存(各用独立子链接)。 // 该 host 是否已有挂起请求(MessageHandle 在 TOKEN_PSLIST/TOKEN_WSLIST 分支调用)。 bool IsPending(uint64_t device_id); // 拷贝响应缓冲到挂起结果并唤醒等待者(在 MessageHandle 内同步调用,数据此时仍在 // context 缓冲中、IO 线程被阻塞,拷贝是安全的)。 void TakeMainResponse(uint64_t device_id, const BYTE* data, ULONG len); // 工具线程:登记挂起(false = 该 host 已有挂起请求,设备忙)。 bool BeginPending(uint64_t device_id, const std::string& tool); // 工具线程:等待响应;成功返回 true 并把缓冲写入 out,超时/失败返回 false(并清理)。 bool WaitPending(uint64_t device_id, std::vector& out, int timeoutMs); // 工具线程:清理挂起状态(发送失败等提前退出路径)。 void ClearPending(uint64_t device_id); private: CMcpServer(); ~CMcpServer(); CMcpServer(const CMcpServer&) = delete; CMcpServer& operator=(const CMcpServer&) = delete; // POST /mcp 处理器:token 校验 + JSON-RPC 分发。 void HandleMcp(const httplib::Request& req, httplib::Response& res); httplib::Server m_server; std::thread m_thread; std::atomic m_running{false}; std::string m_token; CMy2015RemoteDlg* m_parent = nullptr; // 挂起请求注册表(受 m_PendingMutex 保护,键 = device_id)。 struct PendingRequest { std::string tool; std::vector data; bool done = false; }; std::mutex m_PendingMutex; std::condition_variable m_PendingCv; std::map m_Pending; }; // 全局访问器(仿 WebService(),见 WebService.h 末尾) inline CMcpServer& McpServer() { return CMcpServer::Instance(); } // 生成 32 hex(128-bit)随机 token;供运行时兜底与「MCP设置」对话框预填复用。 std::string GenerateRandomToken();