Skip to content

GoodMood2008/sdd-example

Repository files navigation

OPS MCP Server

基于 Model Context Protocol (MCP) 的多服务器框架,支持同时运行多个独立的 MCP 服务器,每个服务器提供不同的功能。

项目简介

本项目是一个 MCP 服务器框架,支持同时运行多个独立的 MCP 服务器实例。当前已实现的服务器包括:

  • CMD MCP Server:提供本地命令执行和SSH远程命令执行功能
    • 本地命令执行:在服务器本地执行 Shell 命令
    • SSH 远程命令执行:通过 SSH 连接远程服务器执行命令
  • File MCP Server:提供受控沙箱内的文件读写能力(默认端口 10002)
    • 创建目录、写入/读取文本文件
    • 列出目录内容、复制文件到指定目录

框架特性:

  • 多服务器支持:可以同时运行多个独立的 MCP 服务器,每个服务器使用不同的端口
  • 多传输方式支持:每个服务器支持 SSE、StreamableHTTP 和组合模式(combined)
  • 健康检查:每个服务器提供独立的 /health 端点用于服务健康检查
  • 统一管理:通过统一的启动/停止脚本管理所有服务器

项目结构

ops_mcp_server/
├── mcp_server/              # MCP 服务器代码
│   ├── cmd_mcp_server/      # CMD MCP 服务器(命令执行服务器)
│   │   ├── server.py        # 服务器主程序
│   │   ├── service.py       # 业务逻辑实现
│   │   └── test_mcp_server.py  # 测试文件
│   ├── file_mcp_server/     # File MCP 服务器(文件管理服务器)
│   │   ├── server.py
│   │   ├── service.py
│   │   └── test_mcp_server.py
│   └── [其他服务器]/        # 可以添加更多服务器模块
│       ├── server.py
│       ├── service.py
│       └── test_mcp_server.py
├── mcp_client/              # MCP 客户端代码
│   ├── cmd_mcp_client.py    # CMD MCP 客户端实现
│   ├── file_mcp_client.py   # File MCP 客户端实现
│   └── [其他客户端]/        # 可以添加更多客户端
├── scripts/                 # 启动/停止脚本
│   ├── run_cmd_mcp_server.sh   # 启动 CMD 服务器脚本
│   ├── stop_cmd_mcp_server.sh  # 停止 CMD 服务器脚本
│   ├── run_file_mcp_server.sh  # 启动 File 服务器脚本
│   ├── stop_file_mcp_server.sh # 停止 File 服务器脚本
│   └── [其他服务器脚本]/    # 可以添加更多服务器脚本
├── run_all_mcp_servers.sh  # 启动所有服务器(统一入口)
├── stop_all_mcp_servers.sh # 停止所有服务器(统一入口)
├── requirements.txt        # Python 依赖包列表
├── INSTALL.md              # 详细安装指南
└── workspace/              # 工作目录(自动创建)
    └── logs/               # 日志目录(自动创建)
        ├── batch_run.log              # 批量启动脚本日志
        ├── run_cmd_mcp_server.log     # CMD 服务器运行日志
        ├── run_cmd_mcp_server_pid.log # CMD 服务器 PID
        └── [其他服务器日志]/          # 其他服务器的日志

环境要求

  • Python 3.8+
  • 虚拟环境:~/mcp_venv(需要预先创建并安装依赖)

核心依赖包

  • mcp - Model Context Protocol 库
  • uvicorn - ASGI 服务器
  • starlette - Web 框架
  • anyio - 异步 IO 库
  • paramiko - SSH 客户端库(用于远程命令执行)
  • pydantic - 数据验证库

测试依赖包(可选)

  • pytest - 测试框架
  • requests - HTTP 请求库

快速开始

1. 安装依赖

重要提示:项目脚本中硬编码了虚拟环境路径为 ~/mcp_venv,请务必在此路径创建虚拟环境。

详细安装步骤请参考 INSTALL.md

快速安装

# 创建虚拟环境(必须在 ~/mcp_venv)
python3 -m venv ~/mcp_venv

# 激活虚拟环境
source ~/mcp_venv/bin/activate

# 安装依赖(推荐使用 requirements.txt)
pip install -r requirements.txt

# 或者仅安装核心依赖(不包含测试依赖)
pip install mcp uvicorn starlette anyio paramiko pydantic

2. 启动服务器

方式一:使用启动脚本(推荐)

# 在项目根目录执行
./run_all_mcp_servers.sh

方式二:手动启动

# 激活虚拟环境
source ~/mcp_venv/bin/activate

# 启动 CMD MCP Server(默认端口 10001,combined 模式)
python3 mcp_server/cmd_mcp_server/server.py --port 10001 --transport combined

# 启动 File MCP Server(默认端口 10002,combined 模式)
python3 mcp_server/file_mcp_server/server.py --port 10002 --transport combined

3. 停止服务器

# 使用停止脚本
./stop_all_mcp_servers.sh

# 或手动停止
./scripts/stop_cmd_mcp_server.sh

配置说明

服务器参数

  • --port: 服务器端口
    • CMD MCP Server 默认 10001
    • File MCP Server 默认 10002
  • --transport: 传输方式,可选值:
    • sse: 仅 SSE 传输
    • streamable-http: 仅 StreamableHTTP 传输
    • combined: 同时支持 SSE 和 StreamableHTTP(默认)
    • stdio: 标准输入输出传输

日志配置

所有日志文件统一保存在 workspace/logs/ 目录下,每个服务器有独立的日志文件:

  • batch_run.log: 批量启动脚本的执行日志(所有服务器共享)
  • run_cmd_mcp_server.log: CMD 服务器运行日志
  • run_cmd_mcp_server_pid.log: CMD 服务器进程 PID 记录
  • run_file_mcp_server.log: File 服务器运行日志
  • run_file_mcp_server_pid.log: File 服务器进程 PID 记录
  • run_[服务器名]_mcp_server.log: 其他服务器的运行日志
  • run_[服务器名]_mcp_server_pid.log: 其他服务器的 PID 记录

多服务器配置

run_all_mcp_servers.shstop_all_mcp_servers.sh 中配置要启动/停止的服务器列表:

# scripts list
SCRIPTS=(
    "scripts/run_cmd_mcp_server.sh"
    "scripts/run_file_mcp_server.sh"
    # 添加更多服务器脚本
    # "scripts/run_xxx_mcp_server.sh"
)

每个服务器使用不同的端口,在对应的启动脚本中配置端口号。

API 接口

CMD MCP Server 工具列表

CMD MCP Server(默认端口 10001)提供以下 MCP 工具:

1. execute_command

执行本地命令

参数:

  • command (string, 必需): 要执行的命令
  • newSession (boolean, 可选): 是否在新会话中执行,默认 false

示例:

{
  "command": "ls -la",
  "newSession": false
}

File MCP Server 工具列表

File MCP Server(默认端口 10002)提供以下工具。所有路径均限定在 workspace/files/ 沙箱根目录下:

1. create_directory

递归创建目录。

参数:

  • path (string, 必需): 相对路径
  • parents (boolean, 可选): 是否递归创建父目录
  • exist_ok (boolean, 可选): 目录存在时是否视为成功
{
  "path": "project/logs",
  "parents": true,
  "exist_ok": true
}

2. write_file

写入 UTF-8 文本文件,可控制覆盖策略。

{
  "path": "project/config.yaml",
  "content": "key: value",
  "overwrite": true
}

3. read_file

读取文本文件,可限制最大读取字节数。

{
  "path": "project/config.yaml",
  "maxBytes": 1048576
}

4. list_directory

列出目录内容,可选择是否递归及最大深度。

{
  "path": "project",
  "recursive": false
}

5. copy_file

复制文件到目标目录,必要时自动创建目录。

{
  "source": "project/config.yaml",
  "targetDir": "archive/2024",
  "overwrite": true
}

2. execute_ssh_command

通过 SSH 执行远程命令

参数:

  • host (string, 必需): 远程主机地址
  • username (string, 必需): SSH 用户名
  • command (string, 必需): 要执行的命令
  • port (integer, 可选): SSH 端口,默认 22
  • password (string, 可选): SSH 密码
  • privateKey (string, 可选): SSH 私钥
  • newSession (boolean, 可选): 是否在新会话中执行,默认 false

示例:

{
  "host": "192.168.1.100",
  "username": "root",
  "command": "df -h",
  "port": 22,
  "password": "your_password"
}

健康检查

每个服务器都提供独立的健康检查端点:

CMD MCP Server(端口 10001):

curl http://localhost:10001/health

File MCP Server(端口 10002):

curl http://localhost:10002/health

其他服务器:

# 根据实际端口访问
curl http://localhost:[端口]/health

返回示例:

{
  "status": "healthy",
  "timestamp": "2024-01-01T12:00:00"
}

客户端使用示例

Python 客户端

import asyncio
from mcp_client.cmd_mcp_client import CmdMcpClient

async def main():
    # 创建客户端(使用 SSE 传输)
    client = CmdMcpClient(
        remote_ip="localhost",
        port=10001,
        transport="sse"
    )
    
    # 执行本地命令
    success, result = await client.execute_command("ls -la")
    print(f"执行结果: {result}")
    
    # 执行 SSH 远程命令
    success, result = await client.execute_ssh_command(
        host="192.168.1.100",
        username="root",
        command="df -h",
        password="your_password"
    )
    print(f"SSH 执行结果: {result}")

if __name__ == "__main__":
    asyncio.run(main())

File MCP Server 客户端

import asyncio
from mcp_client.file_mcp_client import FileMcpClient

async def main():
    client = FileMcpClient(remote_ip="localhost", port=10002, transport="sse")

    # 创建目录
    success, result = await client.create_directory("demo")
    print(success, result)

    # 写入与读取文件
    await client.write_file("demo/hello.txt", "hello file server")
    success, result = await client.read_file("demo/hello.txt")
    print(success, result)

    # 列出目录内容
    success, result = await client.list_directory("demo")
    print(success, result)

if __name__ == "__main__":
    asyncio.run(main())

传输方式说明

SSE (Server-Sent Events)

  • 端点:http://host:port/sse
  • 特点:单向流式传输,适合服务器主动推送数据

StreamableHTTP

  • 端点:http://host:port/mcp
  • 特点:双向流式传输,支持更复杂的交互

Combined 模式

  • 同时支持 SSE 和 StreamableHTTP
  • 客户端可以根据需要选择任意一种传输方式

脚本说明

run_all_mcp_servers.sh

批量启动所有 MCP 服务器的脚本。

功能:

  • 自动创建日志目录
  • 备份已存在的日志文件
  • 按顺序启动所有服务器脚本
  • 记录执行日志到 workspace/logs/batch_run.log

stop_all_mcp_servers.sh

批量停止所有 MCP 服务器的脚本。

功能:

  • 按顺序停止所有服务器
  • 记录执行日志到 workspace/logs/batch_run.log

scripts/run_cmd_mcp_server.sh

启动单个 CMD MCP 服务器的脚本。

功能:

  • 检查服务器是否已在运行
  • 激活虚拟环境
  • 后台启动服务器(默认端口 10001)
  • 记录 PID 和日志

配置说明:

  • 修改 RUN_COMMAND 变量可以更改服务器路径和端口
  • 修改 LOG_FILEPID_FILE 可以更改日志路径

scripts/run_file_mcp_server.sh

启动单个 File MCP 服务器的脚本。

  • 默认端口:10002
  • 激活虚拟环境后后台运行 mcp_server/file_mcp_server/server.py
  • 记录日志到 workspace/logs/run_file_mcp_server.log,PID 记录到 workspace/logs/run_file_mcp_server_pid.log

scripts/stop_cmd_mcp_server.sh

停止单个 CMD MCP 服务器的脚本。

功能:

  • 读取 PID 文件
  • 检查进程是否运行
  • 安全停止服务器进程
  • 清理 PID 文件

scripts/stop_file_mcp_server.sh

停止 File MCP 服务器,逻辑与 CMD 版本一致,PID 文件为 workspace/logs/run_file_mcp_server_pid.log

添加新的 MCP 服务器脚本

当添加新的 MCP 服务器时,需要创建对应的启动和停止脚本:

  1. 创建启动脚本 scripts/run_[服务器名]_mcp_server.sh

    #!/bin/bash
    LOG_FILE="workspace/logs/run_[服务器名]_mcp_server.log"
    PID_FILE="workspace/logs/run_[服务器名]_mcp_server_pid.log"
    mkdir -p "$(dirname "$LOG_FILE")"
    source ~/mcp_venv/bin/activate
    RUN_COMMAND="python3 mcp_server/[服务器目录]/server.py --port [端口号]"
    # ... 其他逻辑参考 run_cmd_mcp_server.sh
  2. 创建停止脚本 scripts/stop_[服务器名]_mcp_server.sh

    #!/bin/bash
    PID_FILE="workspace/logs/run_[服务器名]_mcp_server_pid.log"
    # ... 其他逻辑参考 stop_cmd_mcp_server.sh
  3. 更新批量脚本:在 run_all_mcp_servers.shstop_all_mcp_servers.shSCRIPTS 数组中添加新脚本路径

注意事项

  1. 虚拟环境路径:脚本中硬编码了虚拟环境路径 ~/mcp_venv,如需修改请编辑对应的启动脚本

  2. 端口占用:每个服务器必须使用不同的端口,确保端口未被占用

    • CMD MCP Server 默认端口:10001
    • File MCP Server 默认端口:10002
    • 添加新服务器时,请选择未被占用的端口
  3. 日志目录:所有日志自动保存在 workspace/logs/ 目录,该目录会被自动创建,每个服务器有独立的日志文件

  4. 服务器命名规范:建议使用统一的命名规范

    • 服务器目录:mcp_server/[服务器名]_mcp_server/
    • 启动脚本:scripts/run_[服务器名]_mcp_server.sh
    • 停止脚本:scripts/stop_[服务器名]_mcp_server.sh
    • 日志文件:workspace/logs/run_[服务器名]_mcp_server.log
  5. SSH 连接:使用 SSH 功能需要确保:

    • 目标服务器可访问
    • 提供正确的认证信息(密码或私钥)
    • 网络连接正常
  6. 命令超时:本地命令执行默认超时时间为 5 分钟

  7. 代理设置:代码中会自动清除 HTTP 代理设置,避免云桌面代理问题

  8. 文件沙箱:File MCP Server 仅允许访问 workspace/files/,超出该目录的请求会被拒绝

故障排查

服务器无法启动

  1. 检查虚拟环境是否正确激活
  2. 检查端口是否被占用:netstat -tuln | grep [端口号]
  3. 查看对应服务器的日志文件:workspace/logs/run_[服务器名]_mcp_server.log
  4. 检查启动脚本中的路径和命令是否正确
  5. 确认服务器代码文件存在且可执行

命令执行失败

  1. 检查命令语法是否正确
  2. 检查执行权限
  3. 查看服务器日志获取详细错误信息

SSH 连接失败

  1. 检查网络连通性:ping <host>
  2. 检查 SSH 端口是否正确
  3. 验证用户名和密码/私钥是否正确
  4. 检查目标服务器是否允许 SSH 连接

开发说明

添加新的 MCP 服务器

要添加一个新的 MCP 服务器,请按照以下步骤操作:

1. 创建服务器目录结构

mkdir -p mcp_server/[服务器名]_mcp_server

2. 创建服务器文件

参考 mcp_server/cmd_mcp_server/ 的结构创建以下文件:

  • server.py: 服务器主程序,实现 MCP 服务器逻辑
  • service.py: 业务逻辑实现
  • test_mcp_server.py: 测试文件(可选)

3. 实现服务器逻辑

server.py 中:

from mcp.server.fastmcp import FastMCP
import mcp.types as types

def build_mcp_server(port: int = [端口号]) -> FastMCP:
    mcp = FastMCP(name="[服务器名]_mcp_server", host="0.0.0.0", port=port)
    
    @mcp._mcp_server.list_tools()
    async def list_tools() -> list[types.Tool]:
        # 定义工具列表
        return [...]
    
    @mcp._mcp_server.call_tool()
    async def call_tool(name: str, arguments: dict):
        # 实现工具调用逻辑
        ...
    
    return mcp

4. 创建启动和停止脚本

参考 scripts/run_cmd_mcp_server.shscripts/stop_cmd_mcp_server.sh 创建对应的脚本。

5. 更新批量脚本

run_all_mcp_servers.shstop_all_mcp_servers.shSCRIPTS 数组中添加新脚本:

SCRIPTS=(
    "scripts/run_cmd_mcp_server.sh"
    "scripts/run_[服务器名]_mcp_server.sh"  # 添加新服务器
)

6. 测试新服务器

# 单独测试新服务器
./scripts/run_[服务器名]_mcp_server.sh

# 或批量测试所有服务器
./run_all_mcp_servers.sh

在现有服务器中添加新工具

  1. 在对应服务器的 service.py 中实现业务逻辑
  2. server.pylist_tools() 中注册工具
  3. call_tool() 中添加工具调用逻辑

测试

运行测试文件:

# 测试 CMD MCP Server
python3 mcp_server/cmd_mcp_server/test_mcp_server.py

# 测试其他服务器
python3 mcp_server/[服务器名]_mcp_server/test_mcp_server.py

许可证

[根据实际情况填写]

联系方式

[根据实际情况填写]

About

一个sdd演示库,用于演示sdd+openspec+openspecx

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors