web-server.ts•6.72 kB
import express from "express";
import cors from "cors";
// 存储表单数据
const formSubmissions = new Map<string, any>();
// 数据监听器,用于 open_web_page 工具
const dataListeners = new Map<string, {
resolve: (data: any) => void;
timer: NodeJS.Timeout;
}>();
// 创建Express应用
const app = express();
// 配置中间件
app.use(cors());
app.use(express.json());
app.use(express.static('.'));
// 无需WebSocket连接处理
// 主页路由
app.get('/', (_req: any, res: any) => {
res.send(`
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MCP 通信服务器</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
max-width: 600px;
margin: 50px auto;
padding: 20px;
background-color: #f5f5f5;
}
.container {
background: white;
border-radius: 8px;
padding: 30px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 { color: #333; }
ul { padding-left: 20px; }
li { margin: 10px 0; }
a {
color: #007bff;
text-decoration: none;
padding: 5px 10px;
border-radius: 4px;
transition: background-color 0.2s;
}
a:hover {
background-color: #e9ecef;
}
code {
background-color: #f8f9fa;
padding: 2px 6px;
border-radius: 3px;
font-family: monospace;
}
.status {
background-color: #d4edda;
color: #155724;
padding: 10px;
border-radius: 4px;
margin: 20px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>🚀 MCP 表单服务器</h1>
<div class="status">✅ 服务器正在运行中</div>
<h3>📖 可用页面:</h3>
<ul>
<li><a href="/test-page.html">📝 表单测试页面</a> - HTTP API表单提交测试</li>
</ul>
<h3>🔗 API 端点:</h3>
<ul>
<li><a href="/api/status">📊 服务器状态</a></li>
<li><a href="/api/form-data">📄 表单数据列表</a></li>
</ul>
<h3>📄 表单提交端点:</h3>
<p><code>/api/submit-form</code></p>
<h3>💡 使用说明:</h3>
<p>通过MCP工具 <code>open_web_page</code> 可以打开以下URL:</p>
<ul>
<li><code>http://localhost:${HTTP_PORT}/test-page.html</code></li>
<li><code>http://localhost:${HTTP_PORT}/</code></li>
</ul>
</div>
</body>
</html>
`);
});
// HTTP API端点
app.get('/api/status', (_req: any, res: any) => {
res.json({
status: 'running',
formSubmissions: formSubmissions.size,
pendingListeners: dataListeners.size,
timestamp: new Date().toISOString(),
server: 'MCP Form Server',
version: '1.0.0'
});
});
app.get('/api/form-data', (_req: any, res: any) => {
const submissions = Array.from(formSubmissions.entries()).map(([id, data]) => ({
submissionId: id,
...data
}));
res.json({
submissions,
count: submissions.length,
timestamp: new Date().toISOString()
});
});
// 表单提交API端点
app.post('/api/submit-form', (req: any, res: any) => {
try {
const submissionData = req.body;
const submissionId = `form_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
console.log(`📝 接收到表单提交 ${submissionId}:`, submissionData);
// 存储表单数据
formSubmissions.set(submissionId, {
...submissionData,
submissionId,
submittedAt: new Date().toISOString()
});
// 触发所有等待的监听器
console.log(`🔔 当前有 ${dataListeners.size} 个数据监听器等待`);
dataListeners.forEach((listener, listenerId) => {
console.log(`✅ 触发监听器 ${listenerId}`);
listener.resolve({
submissionId,
data: submissionData,
timestamp: new Date().toISOString()
});
clearTimeout(listener.timer);
dataListeners.delete(listenerId);
});
res.json({
success: true,
message: '表单提交成功',
submissionId
});
} catch (error) {
console.error('表单提交失败:', error);
res.status(500).json({
success: false,
message: '表单提交失败: ' + (error instanceof Error ? error.message : '未知错误')
});
}
});
// 等待页面数据的HTTP API端点
app.post('/api/wait-for-data', (req: any, res: any) => {
const { timeoutMs = 100000 } = req.body;
const listenerId = `http_listener_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
console.error(`⏳ HTTP API: 创建数据监听器 ${listenerId},超时时间: ${timeoutMs}ms`);
const timer = setTimeout(() => {
console.error(`⏰ HTTP API: 监听器 ${listenerId} 超时`);
dataListeners.delete(listenerId);
res.status(408).json({
success: false,
message: `等待页面数据超时 (${timeoutMs}ms)`,
listenerId
});
}, timeoutMs);
dataListeners.set(listenerId, {
resolve: (data) => {
console.error(`🎉 HTTP API: 监听器 ${listenerId} 接收到数据:`, data);
clearTimeout(timer);
res.json({
success: true,
data,
listenerId
});
},
timer
});
});
// 简化的导出函数
export function getFormData(submissionId?: string) {
if (submissionId) {
return formSubmissions.get(submissionId);
}
return Array.from(formSubmissions.entries()).map(([id, data]) => ({
submissionId: id,
...data
}));
}
// 启动Web服务器
const HTTP_PORT = 3003;
function startWebServer() {
app.listen(HTTP_PORT, () => {
console.log(`🌐 表单服务器运行在: http://localhost:${HTTP_PORT}`);
console.log(`📝 表单测试页面: http://localhost:${HTTP_PORT}/test-page.html`);
console.log(`📄 表单提交API: http://localhost:${HTTP_PORT}/api/submit-form`);
});
}
// 如果直接运行此文件,则启动Web服务器
if (import.meta.url.endsWith(process.argv[1].replace(/\\/g, '/'))) {
startWebServer();
}
export { startWebServer };