🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

mcp-interactive-feedback-server

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mcp-interactive-feedback-server - npm Package Compare versions

Comparing version

to
1.0.4

254

index.js

@@ -198,2 +198,29 @@ #!/usr/bin/env node

}
} else if (data.type === 'message') {
// 处理用户主动发送的消息(非回答问题)
log(`收到用户消息: ${data.message}`);
// 这里可以添加处理用户消息的逻辑,比如转发给AI模型
} else if (data.type === 'stop_server') {
log('收到停止服务器请求');
// 发送确认消息给所有客户端
if (state.wsServer) {
state.wsServer.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
type: 'server_stopping',
message: '服务器正在关闭...'
}));
}
});
}
// 延迟一点时间让消息发送完成,然后优雅关闭服务器
setTimeout(async () => {
log('用户请求停止服务器,开始优雅关闭...');
try {
await gracefulShutdown('USER_REQUEST');
} catch (error) {
log(`优雅关闭失败: ${error.message}`);
process.exit(1);
}
}, 1000);
}

@@ -228,120 +255,147 @@ } catch (error) {

// MCP服务器
const server = new McpServer({
name: 'interactive-feedback-mcp',
version: '1.0.0',
});
// MCP服务器封装
const mcpInstance = {
mcpServer: null,
transport: null,
// 注册工具
server.tool(
'ask_user_question',
{ question: z.string().describe('要向用户提出的问题') },
async ({ question }) => {
if (!question) throw new Error('问题不能为空');
try {
if (!state.webServer) {
return { content: [{ type: 'text', text: 'Web服务器未启动' }] };
}
// 等待客户端连接
if (!state.wsServer || state.wsServer.clients.size === 0) {
log(`等待客户端连接: http://localhost:${CONFIG.PORT}`);
await new Promise(resolve => {
const check = () => {
if (state.wsServer && state.wsServer.clients.size > 0) {
resolve();
} else {
setTimeout(check, 1000);
async start() {
this.transport = new StdioServerTransport();
this.mcpServer = new McpServer({
name: "interactive-feedback-server",
version: "1.0.3"
}, {
// ... (MCP配置)
ask: async (ctx, request) => {
state.questionId++;
historyManager.addQuestion(state.questionId, request.question);
if (state.wsServer) {
state.wsServer.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
type: 'new_question',
questionId: state.questionId,
question: request.question,
history: historyManager.getAllHistory() // 发送完整历史以便客户端同步
}));
}
};
check();
});
}
return new Promise((resolve, reject) => {
state.pendingQuestions.set(state.questionId, { resolve, reject });
// 可选:设置超时
// setTimeout(() => {
// if (state.pendingQuestions.has(state.questionId)) {
// state.pendingQuestions.delete(state.questionId);
// reject(new Error('提问超时'));
// }
// }, 60000); // 60秒超时
});
}
// 发送问题
const questionId = ++state.questionId;
historyManager.addQuestion(questionId, question);
log(`发送问题 ${questionId}: ${question.substring(0, 50)}...`);
// 广播新问题
if (state.wsServer) {
state.wsServer.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
type: 'new_question',
questionId,
question,
history: historyManager.getAllHistory()
}));
}
});
}
// 等待回答
const answer = await new Promise((resolve, reject) => {
state.pendingQuestions.set(questionId, { resolve, reject, question });
});
return {
content: [{ type: 'text', text: `用户回答: ${answer}` }]
};
} catch (error) {
return {
content: [{ type: 'text', text: `获取回答失败: ${error.message}` }]
};
});
// 连接传输层
await this.mcpServer.connect(this.transport);
log('MCP服务器已通过Stdio启动');
},
async stop() {
if (this.mcpServer) {
log('正在关闭MCP服务器...');
await this.mcpServer.close();
this.mcpServer = null;
log('MCP服务器已关闭');
}
if (this.transport) {
// StdioTransport 可能不需要显式关闭,或者其关闭已集成在mcpServer.close()中
this.transport = null;
}
}
);
};
async function main() {
try {
historyManager.loadHistory();
await webServer.start(CONFIG.PORT);
await mcpInstance.start();
log(`应用 "${require('./package.json').name}" 版本 "${require('./package.json').version}" 已成功启动。`);
setupShutdownHandlers(); // <--- 添加调用
} catch (error) {
log(`启动失败: ${error.message}`);
console.error('启动失败:', error);
process.exit(1);
}
}
// 优雅关闭处理
function setupShutdownHandlers() {
const shutdown = async (signal) => {
log(`收到 ${signal} 信号,正在关闭...`);
try {
historyManager.saveHistory();
await webServer.stop();
process.exit(0);
} catch (error) {
log(`关闭失败: ${error.message}`);
process.exit(1);
}
await gracefulShutdown(signal);
};
// 监听退出信号
process.on('SIGINT', () => shutdown('SIGINT'));
process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('uncaughtException', (error) => {
log(`未捕获异常: ${error.message}`);
shutdown('uncaughtException');
});
process.on('unhandledRejection', (reason) => {
log(`未处理的Promise拒绝: ${reason}`);
shutdown('unhandledRejection');
});
log('已设置优雅关闭处理程序。');
}
// 主函数
async function main() {
// 优雅关闭函数(可被信号处理和用户请求共用)
async function gracefulShutdown(source) {
log(`接收到信号 ${source}。开始关闭服务...`);
let exitCode = 0;
try {
setupShutdownHandlers();
// 加载历史记录
historyManager.loadHistory();
log('启动Web服务器...');
await webServer.start(CONFIG.PORT);
log('Web服务器启动成功');
log('启动MCP服务器...');
const transport = new StdioServerTransport();
await server.connect(transport);
log('MCP服务器启动成功');
log(`访问: http://localhost:${CONFIG.PORT}`);
// 1. 关闭MCP服务器 (如果它需要先于WebSocket关闭)
await mcpInstance.stop();
// 2. 关闭WebSocket服务器
if (state.wsServer) {
log('正在关闭WebSocket服务器...');
await new Promise((resolve, reject) => {
state.wsServer.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.terminate(); // 强制关闭客户端连接
}
});
state.wsServer.close((err) => {
if (err) {
log(`关闭WebSocket服务器错误: ${err.message}`);
// 不立即将exitCode设为1,继续尝试关闭HTTP服务器
// exitCode = 1;
reject(err); // 但promise应该被reject
return;
}
log('WebSocket服务器已关闭。');
state.wsServer = null;
resolve();
});
});
}
// 3. 关闭HTTP服务器
if (state.webServer) {
log('正在关闭HTTP服务器...');
await new Promise((resolve, reject) => {
state.webServer.close((err) => {
if (err) {
log(`关闭HTTP服务器错误: ${err.message}`);
// exitCode = 1; // 不立即将exitCode设为1
reject(err); // 但promise应该被reject
return;
}
log('HTTP服务器已关闭。');
state.webServer = null;
resolve();
});
});
}
} catch (error) {
log(`启动失败: ${error.message}`);
await webServer.stop();
process.exit(1);
log(`关闭过程中发生错误: ${error.message}`);
exitCode = 1;
} finally {
log(`服务关闭完成,退出码: ${exitCode}`);
process.exit(exitCode);
}

@@ -348,0 +402,0 @@ }

{
"name": "mcp-interactive-feedback-server",
"version": "1.0.3",
"version": "1.0.4",
"description": "一个简洁高效的MCP服务器,支持AI与用户的实时交互问答",

@@ -49,4 +49,5 @@ "main": "index.js",

"ws": "^8.18.2",
"zod": "^3.25.32"
"zod": "^3.25.32",
"zod-to-json-schema": "^3.24.5"
}
}
}

Sorry, the diff of this file is not supported yet