Files
funstat-mcp/docs/ALTERNATIVE_DEPLOYMENT_SOLUTIONS.md
2025-11-01 21:58:03 +08:00

17 KiB
Raw Permalink Blame History

Funstat MCP 工具 - 替代部署方案

🎯 方案概览

除了让每个用户独立部署,还有以下几种完美的永久替代方案:


🌟 方案 1Docker 容器化部署(最推荐)

概述

将 MCP 服务器打包成 Docker 镜像,用户只需一个命令即可启动。

架构

用户 → Docker 容器 → Telegram Session → @openaiw_bot

优势

  • 一键启动docker run 即可
  • 环境隔离:不用担心依赖冲突
  • 跨平台Windows/macOS/Linux 统一
  • 易更新docker pull 拉取新版本
  • 配置简单:环境变量配置
  • 易分发:推送到 Docker Hub

实现步骤

1. 创建 Dockerfile

# Dockerfile
FROM python:3.11-slim

WORKDIR /app

# 安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY funstat_mcp/ /app/
COPY create_session_safe.py /app/

# 创建 session 目录
RUN mkdir -p /app/sessions

# 设置环境变量
ENV TELEGRAM_API_ID=""
ENV TELEGRAM_API_HASH=""
ENV SESSION_DIR="/app/sessions"

# 暴露端口(如果需要)
# EXPOSE 8080

# 启动命令
CMD ["python3", "server.py"]

2. 创建 docker-compose.yml

version: '3.8'

services:
  funstat-mcp:
    build: .
    container_name: funstat-mcp
    environment:
      - TELEGRAM_API_ID=${TELEGRAM_API_ID}
      - TELEGRAM_API_HASH=${TELEGRAM_API_HASH}
    volumes:
      # 持久化 session 文件
      - ./sessions:/app/sessions
    restart: unless-stopped
    stdin_open: true
    tty: true

3. 创建 .env.example

# .env.example
TELEGRAM_API_ID=你的_api_id
TELEGRAM_API_HASH=你的_api_hash

用户使用步骤

# 1. 克隆仓库
git clone https://github.com/your-repo/funstat-mcp-docker.git
cd funstat-mcp-docker

# 2. 配置环境变量
cp .env.example .env
nano .env  # 填入自己的 API 凭证

# 3. 首次创建 session
docker-compose run --rm funstat-mcp python3 create_session_safe.py

# 4. 启动服务
docker-compose up -d

# 5. 查看日志
docker-compose logs -f

配置 Claude Code

{
  "mcpServers": {
    "funstat": {
      "command": "docker",
      "args": [
        "exec",
        "-i",
        "funstat-mcp",
        "python3",
        "server.py"
      ]
    }
  }
}

🌐 方案 2WebSocket 远程服务(推荐用于团队)

概述

部署一个中心化的 MCP 服务器,用户通过 WebSocket 连接使用。

架构

多个用户 → WebSocket → 中心 MCP 服务器 → Session 池 → @openaiw_bot
                ↓
            认证 & 计费

优势

  • 零配置:用户不需要任何本地配置
  • 统一管理:集中维护和更新
  • 权限控制:可以设置用户权限
  • 使用统计:追踪使用量
  • 成本分摊:可以收费或限额

实现步骤

1. 创建 WebSocket 服务器

# ws_server.py
import asyncio
import json
from aiohttp import web
from server import FunstatMCPServer

class WebSocketMCPServer:
    def __init__(self):
        self.clients = {}
        self.mcp_server = FunstatMCPServer()

    async def handle_websocket(self, request):
        ws = web.WebSocketResponse()
        await ws.prepare(request)

        # 认证
        auth_msg = await ws.receive_json()
        token = auth_msg.get('token')

        if not self.verify_token(token):
            await ws.send_json({'error': 'Invalid token'})
            await ws.close()
            return ws

        client_id = auth_msg.get('client_id')
        self.clients[client_id] = ws

        try:
            async for msg in ws:
                if msg.type == web.WSMsgType.TEXT:
                    data = json.loads(msg.data)

                    # 调用 MCP 工具
                    result = await self.mcp_server.call_tool(
                        data['tool'],
                        data['arguments']
                    )

                    # 返回结果
                    await ws.send_json({
                        'id': data['id'],
                        'result': result
                    })

        finally:
            del self.clients[client_id]

        return ws

    def verify_token(self, token):
        # 实现你的认证逻辑
        return token in self.valid_tokens

    async def start(self):
        await self.mcp_server.initialize()

        app = web.Application()
        app.router.add_get('/ws', self.handle_websocket)

        runner = web.AppRunner(app)
        await runner.setup()
        site = web.TCPSite(runner, '0.0.0.0', 8080)
        await site.start()

if __name__ == '__main__':
    server = WebSocketMCPServer()
    asyncio.run(server.start())

2. 创建客户端库

# client.py
import asyncio
import json
import websockets

class FunstatMCPClient:
    def __init__(self, url, token):
        self.url = url
        self.token = token
        self.ws = None

    async def connect(self):
        self.ws = await websockets.connect(self.url)

        # 认证
        await self.ws.send(json.dumps({
            'token': self.token,
            'client_id': 'user-123'
        }))

    async def call_tool(self, tool, arguments):
        msg = {
            'id': str(uuid.uuid4()),
            'tool': tool,
            'arguments': arguments
        }

        await self.ws.send(json.dumps(msg))
        response = await self.ws.recv()

        return json.loads(response)

    async def close(self):
        await self.ws.close()

用户使用

# 用户端代码
import asyncio
from client import FunstatMCPClient

async def main():
    client = FunstatMCPClient(
        url='ws://your-server.com:8080/ws',
        token='user-token-here'
    )

    await client.connect()

    result = await client.call_tool(
        'funstat_search',
        {'query': 'python'}
    )

    print(result)

    await client.close()

asyncio.run(main())

部署到云服务器

# 使用 Docker + Nginx
docker-compose -f docker-compose.prod.yml up -d

📦 方案 3NPM 包发布(适合开发者)

概述

将 MCP 服务器打包成 NPM 包,通过 npx 一键运行。

架构

用户 → npx funstat-mcp → 本地 MCP 服务器 → @openaiw_bot

优势

  • 一键安装npx funstat-mcp
  • 自动更新npx 自动使用最新版本
  • 开发者友好:熟悉的工具链
  • 易维护:集中发布更新

实现步骤

1. 创建 Node.js 包装器

// index.js
#!/usr/bin/env node

const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs');
const os = require('os');

// 配置目录
const configDir = path.join(os.homedir(), '.funstat-mcp');
const sessionPath = path.join(configDir, 'session');

// 确保配置目录存在
if (!fs.existsSync(configDir)) {
    fs.mkdirSync(configDir, { recursive: true });
}

// 检查是否首次运行
if (!fs.existsSync(path.join(configDir, '.env'))) {
    console.log('首次运行,开始配置...');

    const readline = require('readline').createInterface({
        input: process.stdin,
        output: process.stdout
    });

    readline.question('请输入 API ID: ', (apiId) => {
        readline.question('请输入 API Hash: ', (apiHash) => {
            // 保存配置
            const config = `TELEGRAM_API_ID=${apiId}\nTELEGRAM_API_HASH=${apiHash}\n`;
            fs.writeFileSync(path.join(configDir, '.env'), config);

            console.log('配置已保存!');
            readline.close();

            // 创建 session
            createSession();
        });
    });
} else {
    // 启动服务器
    startServer();
}

function startServer() {
    const serverPath = path.join(__dirname, 'python', 'server.py');
    const server = spawn('python3', [serverPath], {
        env: {
            ...process.env,
            SESSION_PATH: sessionPath
        },
        stdio: 'inherit'
    });

    server.on('exit', (code) => {
        console.log(`服务器退出,代码: ${code}`);
    });
}

function createSession() {
    const scriptPath = path.join(__dirname, 'python', 'create_session_safe.py');
    const proc = spawn('python3', [scriptPath], {
        env: {
            ...process.env,
            SESSION_PATH: sessionPath
        },
        stdio: 'inherit'
    });

    proc.on('exit', () => {
        console.log('Session 创建完成!');
        startServer();
    });
}

2. 创建 package.json

{
  "name": "@yourname/funstat-mcp",
  "version": "1.0.0",
  "description": "Funstat MCP Server - One-command deployment",
  "bin": {
    "funstat-mcp": "./index.js"
  },
  "scripts": {
    "postinstall": "python3 -m pip install -r python/requirements.txt"
  },
  "keywords": ["mcp", "telegram", "funstat"],
  "author": "Your Name",
  "license": "MIT",
  "files": [
    "index.js",
    "python/"
  ],
  "engines": {
    "node": ">=14.0.0"
  }
}

用户使用

# 首次运行(自动配置)
npx @yourname/funstat-mcp

# 之后直接运行
npx @yourname/funstat-mcp

🚀 方案 4Electron 桌面应用(最用户友好)

概述

打包成独立的桌面应用,带图形界面配置。

架构

用户 → Electron GUI → 本地 MCP 服务器 → @openaiw_bot

优势

  • 图形界面:无需命令行
  • 一键安装:下载 .dmg/.exe 即可
  • 自动更新electron-updater
  • 状态显示:可视化连接状态
  • 配置管理GUI 配置界面

实现步骤

1. 创建 Electron 主进程

// main.js
const { app, BrowserWindow, ipcMain } = require('electron');
const { spawn } = require('child_process');
const path = require('path');

let mainWindow;
let mcpProcess;

function createWindow() {
    mainWindow = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false
        }
    });

    mainWindow.loadFile('index.html');
}

app.whenReady().then(createWindow);

// 启动 MCP 服务器
ipcMain.on('start-server', (event, config) => {
    const serverPath = path.join(__dirname, 'python', 'server.py');

    mcpProcess = spawn('python3', [serverPath], {
        env: {
            ...process.env,
            TELEGRAM_API_ID: config.apiId,
            TELEGRAM_API_HASH: config.apiHash
        }
    });

    mcpProcess.stdout.on('data', (data) => {
        event.reply('server-log', data.toString());
    });

    mcpProcess.on('exit', (code) => {
        event.reply('server-stopped', code);
    });
});

// 停止服务器
ipcMain.on('stop-server', () => {
    if (mcpProcess) {
        mcpProcess.kill();
    }
});

2. 创建前端界面

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Funstat MCP</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
            padding: 20px;
        }
        .config-form {
            max-width: 500px;
            margin: 0 auto;
        }
        input {
            width: 100%;
            padding: 10px;
            margin: 10px 0;
            border: 1px solid #ccc;
            border-radius: 4px;
        }
        button {
            background: #007bff;
            color: white;
            padding: 10px 20px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        .status {
            margin-top: 20px;
            padding: 10px;
            border-radius: 4px;
        }
        .status.running {
            background: #d4edda;
            color: #155724;
        }
        .status.stopped {
            background: #f8d7da;
            color: #721c24;
        }
    </style>
</head>
<body>
    <h1>🚀 Funstat MCP Server</h1>

    <div class="config-form">
        <h2>配置</h2>

        <label>API ID:</label>
        <input type="text" id="apiId" placeholder="输入你的 API ID">

        <label>API Hash:</label>
        <input type="text" id="apiHash" placeholder="输入你的 API Hash">

        <button onclick="startServer()">启动服务器</button>
        <button onclick="stopServer()">停止服务器</button>

        <div id="status" class="status stopped">
            服务器状态:已停止
        </div>

        <div id="logs" style="margin-top: 20px; height: 300px; overflow-y: auto; background: #f5f5f5; padding: 10px; border-radius: 4px;">
            <h3>日志</h3>
            <pre id="logContent"></pre>
        </div>
    </div>

    <script src="renderer.js"></script>
</body>
</html>

3. 创建渲染进程脚本

// renderer.js
const { ipcRenderer } = require('electron');

function startServer() {
    const config = {
        apiId: document.getElementById('apiId').value,
        apiHash: document.getElementById('apiHash').value
    };

    if (!config.apiId || !config.apiHash) {
        alert('请填写 API 凭证');
        return;
    }

    // 保存配置
    localStorage.setItem('config', JSON.stringify(config));

    // 启动服务器
    ipcRenderer.send('start-server', config);

    document.getElementById('status').className = 'status running';
    document.getElementById('status').textContent = '服务器状态:运行中';
}

function stopServer() {
    ipcRenderer.send('stop-server');

    document.getElementById('status').className = 'status stopped';
    document.getElementById('status').textContent = '服务器状态:已停止';
}

// 监听日志
ipcRenderer.on('server-log', (event, log) => {
    const logContent = document.getElementById('logContent');
    logContent.textContent += log;
    logContent.scrollTop = logContent.scrollHeight;
});

// 恢复配置
window.addEventListener('DOMContentLoaded', () => {
    const savedConfig = localStorage.getItem('config');
    if (savedConfig) {
        const config = JSON.parse(savedConfig);
        document.getElementById('apiId').value = config.apiId;
        document.getElementById('apiHash').value = config.apiHash;
    }
});

打包和分发

# 安装依赖
npm install electron electron-builder --save-dev

# 打包
npm run build

# 生成安装包
# macOS: Funstat-MCP-1.0.0.dmg
# Windows: Funstat-MCP-Setup-1.0.0.exe
# Linux: Funstat-MCP-1.0.0.AppImage

用户使用

  1. 下载安装包
  2. 双击安装
  3. 打开应用
  4. 输入 API 凭证
  5. 点击"启动服务器"
  6. 完成!

🌍 方案 5SaaS 服务(商业化)

概述

提供完全托管的云服务,用户注册账号即可使用。

架构

用户浏览器 → Web 界面 → API Gateway → MCP Server Pool → @openaiw_bot
                          ↓
                    认证、计费、监控

优势

  • 零配置:注册即用
  • 跨设备:任何设备访问
  • 托管服务:无需维护
  • 付费模式:可以商业化
  • 企业功能:团队管理、审计日志

技术栈

前端: React + TypeScript
后端: FastAPI + Python
数据库: PostgreSQL
缓存: Redis
消息队列: RabbitMQ
部署: Kubernetes + Docker

功能模块

  1. 用户管理

    • 注册/登录
    • OAuth 集成
    • 团队管理
  2. 计费系统

    • 按使用量计费
    • 订阅套餐
    • 积分系统
  3. API 网关

    • 速率限制
    • 请求认证
    • 负载均衡
  4. 监控系统

    • 使用统计
    • 性能监控
    • 错误追踪
  5. 管理后台

    • 用户管理
    • 使用分析
    • 配置管理

📊 方案对比

方案 难度 用户体验 维护成本 扩展性 推荐度
Docker
WebSocket
NPM 包
Electron
SaaS

🎯 推荐选择

个人/小团队(< 10人

推荐Docker 容器化

  • 简单易用
  • 成本低
  • 易维护

中型团队10-50人

推荐WebSocket 远程服务

  • 集中管理
  • 统一维护
  • 权限控制

大型组织(> 50人

推荐SaaS 服务

  • 完全托管
  • 企业功能
  • 可商业化

非技术用户

推荐Electron 桌面应用

  • 图形界面
  • 一键安装
  • 零配置

🚀 快速实施建议

阶段 1立即可用本周

  • 创建 Docker 镜像
  • 发布到 Docker Hub
  • 更新文档

阶段 2团队版本1个月

  • 开发 WebSocket 服务器
  • 部署到云服务器
  • 添加认证系统

阶段 3桌面应用2个月

  • 开发 Electron 应用
  • 打包分发
  • 自动更新

阶段 4SaaS 化3-6个月

  • 完整的 Web 平台
  • 计费系统
  • 企业功能

每种方案都有完整的实现路径,可以根据需求选择! 🎊