MCP服务器SSE桥接

提供安全、持久的HTTP/SSE桥接服务,支持多种MCP服务器(如TaskMaster-AI、Playwright等)的远程访问和实时数据流传输。

  • by gitvj
  • Shell
  • 本地部署
  • 更新于
在 GitHub 查看 gitvj/mcp_sse_server

使用说明

🚀 MCP SSE服务器-安全且持久

用于具有企业级安全功能的模型上下文协议(MCP)服务器的安全、持久的HTTP/SSE网桥。

🌟 特性

✅ 企业安全 -令牌认证、IP白名单、速率限制
✅ 持续操作 -在终端关闭后幸存,开机时自动启动
✅ 多个MCP服务器 -TaskMaster AI、剧作家、木偶师、PostgreSQL、GitHub、Context7
✅ 实时SSE -来自MCP服务器的实时流媒体
✅ 生产就绪 -PM2、systemd、Docker部署选项
✅ 远程访问 -从任何机器访问MCP服务器
✅ 综合文档 -安全指南、客户示例、故障排除

🚀 快速部署(Ubuntu)

# 1. Clone repository
git clone https://github.com/gitvj/mcp_sse_server.git
cd mcp_sse_server

# 2. Run automated setup
./deploy.sh

# 3. Your secure MCP server is running! 🎉

就是这样! 部署脚本处理一切:依赖关系、安全性、持久性。

⚠️ 安全通知

此服务器包括 企业级安全 默认情况下:

  • 🔐 承载令牌身份验证 所有MCP端点都需要
  • 🛡️ IP白名单 -只允许使用受信任的IP
  • ⚡ 速率限制 -DoS保护(100个要求/15分钟)
  • 🔒 环境变量 -安全的API密钥存储
  • 📋 审计日志 -跟踪的所有安全事件

看 安全.md 获取完整的安全文档。

📚 文档

文件 目的
快速启动.md 快速设置指南
安全.md 完整的安全指南
客户指南.md 如何从客户端应用程序连接
部署.md 生产部署选项
它是如何工作的.md 技术架构

🎯 用例

  • 远程MCP访问 -从任何机器访问TaskMaster AI
  • Web应用程序 -通过HTTP/SSE将MCP服务器集成到web应用程序中
  • 开发团队 -共享MCP服务器基础架构
  • 生产部署 -可扩展的MCP服务器托管
  • 跨平台访问 -Windows/Mac客户端→ Linux MCP服务器

📋 先决条件

✅ Node.js v2015.1(已通过NVM安装)
✅ npm和npx(已经可用)
✅ MCP工具(任务主管ai、剧作家服务器)

🔧 安装

  1. 依赖项已安装:

    # Already done:
    # npm install express cors dotenv
    
  2. 创建server.js:

    cat > server.js << 'EOF'
    const express = require('express');
    const cors = require('cors');
    const { spawn } = require('child_process');
    
    const app = express();
    const PORT = process.env.PORT || 3001;
    
    app.use(cors());
    app.use(express.json());
    
    const mcpProcesses = new Map();
    
    const mcpConfigs = {
        'taskmaster-ai': {
            command: 'task-master-ai',
            args: [],
            env: {
                ANTHROPIC_API_KEY: "YOUR_ANTHROPIC_API_KEY_HERE",
                PERPLEXITY_API_KEY: "YOUR_PERPLEXITY_API_KEY_HERE",
                MODEL: "claude-3-7-sonnet-20250219"
            }
        },
        'playwright1': {
            command: 'npx',
            args: ['@playwright/mcp@latest'],
            env: {}
        },
        'playwright2': {
            command: 'npx',
            args: ['-y', '@executeautomation/playwright-mcp-server'],
            env: {}
        },
        'puppeteer': {
            command: 'npx',
            args: ['-y', '@modelcontextprotocol/server-puppeteer'],
            env: {}
        }
    };
    
    function startMcpProcess(serverName, config) {
        console.log(`Starting MCP server: ${serverName}`);
        const process = spawn(config.command, config.args, {
            env: { ...process.env, ...config.env },
            stdio: ['pipe', 'pipe', 'pipe']
        });
        
        process.stdout.on('data', (data) => {
            console.log(`[${serverName}] ${data}`);
        });
        
        process.stderr.on('data', (data) => {
            console.error(`[${serverName}] ERROR: ${data}`);
        });
        
        mcpProcesses.set(serverName, { process, config });
        return process;
    }
    
    // SSE endpoint
    app.get('/mcp/:server/sse', (req, res) => {
        const serverName = req.params.server;
        
        if (!mcpConfigs[serverName]) {
            return res.status(404).json({ error: 'Server not found' });
        }
    
        res.writeHead(200, {
            'Content-Type': 'text/event-stream',
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive',
            'Access-Control-Allow-Origin': '*'
        });
    
        if (!mcpProcesses.has(serverName)) {
            startMcpProcess(serverName, mcpConfigs[serverName]);
        }
    
        const mcpData = mcpProcesses.get(serverName);
        
        if (mcpData) {
            const dataHandler = (data) => {
                res.write(`data: ${JSON.stringify({ type: 'output', data: data.toString() })}\n\n`);
            };
    
            mcpData.process.stdout.on('data', dataHandler);
            mcpData.process.stderr.on('data', dataHandler);
    
            req.on('close', () => {
                mcpData.process.stdout.removeListener('data', dataHandler);
                mcpData.process.stderr.removeListener('data', dataHandler);
            });
        }
    
        const keepAlive = setInterval(() => {
            res.write(`data: ${JSON.stringify({ type: 'ping', timestamp: Date.now() })}\n\n`);
        }, 30000);
    
        req.on('close', () => {
            clearInterval(keepAlive);
        });
    });
    
    // API endpoints
    app.get('/mcp/servers', (req, res) => {
        const servers = Object.keys(mcpConfigs).map(name => ({
            name,
            running: mcpProcesses.has(name),
            config: mcpConfigs[name]
        }));
        res.json(servers);
    });
    
    app.post('/mcp/:server/start', (req, res) => {
        const serverName = req.params.server;
        if (!mcpConfigs[serverName]) {
            return res.status(404).json({ error: 'Server not found' });
        }
        if (mcpProcesses.has(serverName)) {
            return res.json({ status: 'already_running' });
        }
        try {
            startMcpProcess(serverName, mcpConfigs[serverName]);
            res.json({ status: 'started', server: serverName });
        } catch (error) {
            res.status(500).json({ error: error.message });
        }
    });
    
    app.post('/mcp/:server/command', (req, res) => {
        const serverName = req.params.server;
        const { command } = req.body;
    
        if (!mcpConfigs[serverName]) {
            return res.status(404).json({ error: 'Server not found' });
        }
    
        if (!mcpProcesses.has(serverName)) {
            startMcpProcess(serverName, mcpConfigs[serverName]);
        }
    
        const mcpData = mcpProcesses.get(serverName);
        
        if (mcpData && mcpData.process) {
            try {
                mcpData.process.stdin.write(JSON.stringify(command) + '\n');
                res.json({ status: 'sent', command });
            } catch (error) {
                res.status(500).json({ error: error.message });
            }
        } else {
            res.status(503).json({ error: 'MCP server not available' });
        }
    });
    
    app.get('/', (req, res) => {
        res.send(`
        <h1>🚀 MCP SSE Server</h1>
        <p>Available servers: ${Object.keys(mcpConfigs).join(', ')}</p>
        <p><a href="/mcp/servers">Check server status (JSON)</a></p>
        <h2>API Endpoints:</h2>
        <ul>
            <li><strong>GET /mcp/servers</strong> - List all servers</li>
            <li><strong>GET /mcp/{server}/sse</strong> - SSE stream for server</li>
            <li><strong>POST /mcp/{server}/start</strong> - Start a server</li>
            <li><strong>POST /mcp/{server}/command</strong> - Send command to server</li>
        </ul>
        `);
    });
    
    app.listen(PORT, '0.0.0.0', () => {
        console.log(`🚀 MCP SSE Server running on http://0.0.0.0:${PORT}`);
        console.log('📍 Access from:');
        console.log(`   🔒 Local: http://localhost:${PORT}`);
        
        const os = require('os');
        const interfaces = os.networkInterfaces();
        for (const name of Object.keys(interfaces)) {
            for (const iface of interfaces[name]) {
                if (iface.family === 'IPv4' && !iface.internal) {
                    console.log(`   🌐 Network: http://${iface.address}:${PORT}`);
                }
            }
        }
    });
    EOF
    
  3. 启动服务器:

    node server.js
    

🔥 防火墙配置

适用于AWS EC2:为安全组中的端口3001添加入站规则 对于UFW: sudo ufw allow 3001

📡 从远程计算机使用

连接到SSE流

const eventSource = new EventSource('http://YOUR_IP:3001/mcp/taskmaster-ai/sse');
eventSource.onmessage = function(event) {
    const data = JSON.parse(event.data);
    console.log('Received:', data);
};

发送命令

fetch('http://YOUR_IP:3001/mcp/taskmaster-ai/command', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ command: 'your-mcp-command' })
});

列出可用服务器

curl http://YOUR_IP:3001/mcp/servers

🎯 后续步骤

  1. 配置防火墙以允许端口3001
  2. 获取您的公共IP: curl http://checkip.amazonaws.com
  3. 从另一台机器进行测试: curl http://YOUR_IP:3001/
  4. 开始远程使用MCP!

🔧 故障排除

  • 正在使用的端口:更改.env文件中的PORT
  • 连接被拒绝:检查防火墙设置
  • MCP服务器未启动:验证配置中的API密钥