MCP协议聚合服务

一个基于Go的MCP协议聚合中心,通过统一的HTTP API暴露多个MCP服务器的工具。

  • by amir-the-h
  • Go
  • 本地部署
  • 更新于
在 GitHub 查看 amir-the-h/mcp-hub

使用说明

MCP集线器

一个基于Go-based的集线器,聚合多个MCP(模型上下文协议)服务器,并通过统一的HTTP API公开其工具。

特性

  • 标准MCP协议:完全支持MCP 2024-11-05规范
  • 多种运输方式:
    • Stdio:用于本地MCP服务器(Node.js、Python等)
    • HTTP/SSE:用于远程MCP服务器
  • 基于配置:JSON配置与游标/VCode格式兼容
  • Docker就绪:易于在具有卷装的容器中部署
  • 工具聚合:将来自多个MCP服务器的工具组合在一个地方
  • HTTP API:用于工具发现和执行的RESTful端点

快速开始

1.建造

cd cmd/mcp-hub
go build -o ../../mcp-hub

2.创建配置

创建一个 config.json 文件(参见 config.example.json 对于模板):

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
      }
    }
  }
}

3.跑步

# Using default config.json
./mcp-hub

# Or specify a config file
./mcp-hub --config /path/to/config.json

笔记:

  • HTTP侦听地址可以用以下命令覆盖 MCP_HUB_PORT 或 PORT 环境变量。如果该值包含冒号,则将其视为完整地址(例如。 0.0.0.0:8080),否则它将被视为端口,并以冒号作为前缀。
  • 二进制文件接受 --config 标志(默认值: config.json).

4.使用API

列出所有可用工具:

curl http://localhost:8080/mcp/tools

执行工具:

curl -X POST http://localhost:8080/mcp/execute \
  -H 'Content-Type: application/json' \
  -d '{
    "plugin_id": "filesystem",
    "tool_name": "read_file",
    "arguments": {"path": "/tmp/test.txt"}
  }'

列出已连接的服务器:

curl http://localhost:8080/mcp/servers

配置格式

配置文件使用标准 mcpServers 格式与Cursor、VSCode和Claude Desktop兼容。

标准服务器(本地)

对于作为本地进程运行的MCP服务器:

{
  "mcpServers": {
    "server-name": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-package"],
      "env": {
        "API_KEY": "${YOUR_API_KEY}"
      },
      "timeout": 30
    }
  }
}

领域:

  • command:要运行的可执行文件(必需)
  • args:命令行参数(可选)
  • env:环境变量(可选,支持 ${VAR} 扩展)
  • timeout:请求超时(秒)(可选,默认值:30)
  • disabled:设置为 true 禁用服务器(可选)

HTTP服务器(远程)

对于可通过HTTP访问的MCP服务器:

{
  "mcpServers": {
    "remote-server": {
      "type": "http",
      "url": "http://localhost:3000/mcp",
      "headers": {
        "Authorization": "Bearer ${API_TOKEN}"
      },
      "timeout": 45
    }
  }
}

领域:

  • type:设置为 "http" 用于HTTP传输(或从自动检测 url)
  • url:HTTP端点URL(必需)
  • headers:要包含的HTTP标头(可选,支持 ${VAR} 扩展)
  • timeout:请求超时(秒)(可选,默认值:30)

环境变量

配置中的环境变量通过以下方式展开 ${VAR_NAME} 语法。例如:

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
      }
    }
  }
}

然后运行:

GITHUB_TOKEN=your_token_here ./mcp-hub

Docker部署

图像变体

该存储库提供了两个Docker镜像变体,针对不同的用例进行了优化:

1. 标准图像 (Dockerfile / mcp-hub:latest)

  • 尺寸:~47MB
  • 包含:Alpine Linux+Docker CLI+mcp-hub二进制文件
  • 使用时间:在容器中运行MCP服务器需要Docker传输,或混合传输
  • 最适合:使用基于容器的MCP服务器进行生产部署

2. 本地MCP服务器映像 (Dockerfile.local / mcp-hub:local)

  • 尺寸:约800MB
  • 包含:Node.js 20、Python 3、uv、curl、git和mcp-hub二进制文件
  • 使用时间:您希望在同一容器中运行基于stdio的本地MCP服务器(Node.js、Python)
  • 最适合:集线器和所有MCP服务器一起运行的独立部署

构建Docker镜像

要在本地构建特定映像,请执行以下操作:

# Standard image (with Docker CLI)
docker build -t mcp-hub:latest .

# Local MCP servers image (with Node.js, Python, uv)
docker build -f Dockerfile.local -t mcp-hub:local .

使用Docker运行

# Create a config directory
mkdir -p config

# Put your config.json in the config directory
cp config.json config/

# Run the container
docker run -d \
  -p 8080:8080 \
  -v $(pwd)/config:/config:ro \
  -e GITHUB_TOKEN=${GITHUB_TOKEN} \
  mcp-hub

Docker Compose

version: '3.8'
services:
  mcp-hub:
    build: .
    ports:
      - "8080:8080"
    volumes:
      - ./config:/config:ro
      - ./plugins:/plugins:ro  # Optional: mount custom plugins
    environment:
      - GITHUB_TOKEN=${GITHUB_TOKEN}
      - BRAVE_API_KEY=${BRAVE_API_KEY}

HTTP API参考

GET/mcp/工具

列出所有连接的MCP服务器中的所有可用工具。

答复:

[
  {
    "id": "read_file",
    "name": "read_file",
    "description": "Read contents of a file",
    "plugin_id": "filesystem"
  }
]

POST/mcp/执行

在特定的MCP服务器上执行工具。

请求:

{
  "plugin_id": "filesystem",
  "tool_name": "read_file",
  "arguments": {
    "path": "/tmp/test.txt"
  }
}

答复: MCP工具调用结果(格式取决于工具)

GET/mcp/服务器

列出所有连接的MCP服务器。

答复:

{
  "servers": ["filesystem", "github", "brave-search"]
}

GET/mcp/stream

服务器发送的工具注册表更新事件流(用于实时工具发现)。

示例

示例1:使用官方MCP服务器

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/documents"]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
      }
    },
    "brave-search": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-brave-search"],
      "env": {
        "BRAVE_API_KEY": "${BRAVE_API_KEY}"
      }
    }
  }
}

示例2:自定义Python MCP服务器

{
  "mcpServers": {
    "custom-tools": {
      "command": "python3",
      "args": ["/app/plugins/custom_mcp_server.py"]
    }
  }
}

示例3:混合本地和远程服务器

{
  "mcpServers": {
    "local-filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/data"]
    },
    "remote-api": {
      "type": "http",
      "url": "https://api.example.com/mcp",
      "headers": {
        "Authorization": "Bearer ${API_TOKEN}"
      }
    }
  }
}

发展

项目结构

.
├── cmd/
│   └── mcp-hub/
│       └── main.go           # Entry point
├── internal/
│   ├── config/
│   │   └── config.go         # Configuration parsing
│   ├── mcp/
│   │   └── protocol.go       # MCP protocol structures
│   ├── plugin/
│   │   └── manager.go        # Server management
│   ├── registry/
│   │   └── registry.go       # Tool registry
│   ├── server/
│   │   └── server.go         # HTTP server
│   └── transport/
│       ├── transport.go      # Transport interface
│       ├── stdio.go          # Stdio transport
│       └── http.go           # HTTP transport
├── config.example.json       # Example configuration
└── README.md

添加新的传输类型

实施 Transport 接口在 internal/transport/:

type Transport interface {
    Start(ctx context.Context) error
    SendRequest(ctx context.Context, req interface{}) (json.RawMessage, error)
    SendNotification(ctx context.Context, notification interface{}) error
    Close() error
    IsConnected() bool
}

故障排除

服务器无法启动

检查日志中的特定错误消息。常见问题:

  • 缺失 npx 或 python3 在PATH中
  • MCP服务器包名称无效
  • 缺少环境变量
  • 配置中的文件路径不正确

工具执行失败

  • 验证MCP服务器是否已正确初始化(检查 /mcp/servers)
  • 确保工具参数与预期的架构匹配
  • 检查服务器日志(stderr输出在集线器日志中可见)

超时错误

增加 timeout 服务器配置中的值:

{
  "mcpServers": {
    "slow-server": {
      "command": "...",
      "timeout": 120
    }
  }
}

许可证

麻省理工学院

Docker服务器(容器化)

对于在Docker容器中运行的MCP服务器:

{
  "mcpServers": {
    "containerized-server": {
      "type": "docker",
      "image": "my-mcp-server:latest",
      "args": ["--option", "value"],
      "env": {
        "API_KEY": "${YOUR_API_KEY}"
      },
      "volumes": {
        "/host/path": "/container/path",
        "${HOME}/data": "/data"
      },
      "network": "mcp-network",
      "timeout": 60
    }
  }
}

领域:

  • type:设置为 "docker" 用于Docker传输(或从中自动检测 image)
  • image:Docker镜像名称(必填)
  • args:传递给容器入口点的命令参数(可选)
  • env:环境变量(可选,支持 ${VAR} 扩展)
  • volumes:卷装载为 host:container 映射(可选,支持 ${VAR} 扩展)
  • network:要连接的Docker网络(可选)
  • timeout:请求超时(秒)(可选,默认值:30)

Docker传输的好处:

  • 无需在中心主机上安装Node.js、Python或其他运行时
  • 每个MCP服务器的独立依赖关系
  • 使用Docker标签轻松管理版本
  • 跨部署的一致环境

为MCP服务器构建Docker镜像

您可以将任何MCP服务器容器化,以避免将其依赖项安装在集线器主机上。

示例:对Python MCP服务器进行Docker化

Dockerfile:

FROM python:3.11-slim

WORKDIR /app

# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy MCP server code
COPY mcp_server.py .

# Run as non-root user
RUN useradd -m -u 1000 mcpuser && chown -R mcpuser:mcpuser /app
USER mcpuser

# The server should read from stdin and write to stdout
ENTRYPOINT ["python", "-u", "mcp_server.py"]

构建和使用:

# Build the image
docker build -t my-mcp-server:latest .

# Add to config.json
{
  "mcpServers": {
    "my-server": {
      "image": "my-mcp-server:latest"
    }
  }
}

示例:对Node.js MCP服务器进行码头化

Dockerfile:

FROM node:20-alpine

WORKDIR /app

# Install dependencies
COPY package*.json ./
RUN npm ci --production

# Copy server code
COPY . .

# Run as non-root user
RUN addgroup -g 1000 mcpuser && \
    adduser -D -u 1000 -G mcpuser mcpuser && \
    chown -R mcpuser:mcpuser /app
USER mcpuser

ENTRYPOINT ["node", "server.js"]

Docker MCP服务器的重要注意事项

  1. 使用 -i 旗帜:枢纽运行集装箱 docker run -i 用于交互式stdin/stdout
  2. 无缓冲输出:确保您的服务器输出没有缓冲(使用 python -u 或 flush())
  3. 仅限标准输入/标准输出:MCP协议使用stdin作为输入,stdout作为输出
  4. 日志标准错误:使用stderr进行日志记录(在集线器日志中可见)
  5. 清理:容器与一起运行 --rm 用于自动清理

预构建的MCP服务器映像

为常见的MCP服务器创建Docker映像注册表:

# Example: Build an echo server image
cd examples/plugins
cat > Dockerfile << 'DOCKERFILE'
FROM python:3.11-slim
COPY mcp_echo.py /app/server.py
WORKDIR /app
RUN chmod +x server.py
ENTRYPOINT ["python", "-u", "server.py"]
DOCKERFILE

docker build -t mcp-echo:latest .

然后使用它:

{
  "mcpServers": {
    "echo": {
      "image": "mcp-echo:latest"
    }
  }
}

运输比较

运输 用例 优点 缺点
标准 可直接访问的本地MCP服务器 快速、低开销 需要安装运行时(Node.js/Python)
码头工人 独立、可复制的MCP服务器 无运行时依赖关系,易于版本控制 开销稍高,需要Docker
超文本传输协议 远程/云托管MCP服务器 可扩展,可以负载平衡 网络延迟,需要服务器基础设施

何时使用Docker传输

在以下情况下选择Docker传输:

  • ✅ 您希望避免在中心主机上安装Node.js、Python或其他运行时环境
  • ✅ 您需要跨部署的一致、可重复的环境
  • ✅ 您希望使用Docker标签进行简单的版本管理
  • ✅ 您正在容器化环境(Kubernetes、Docker Compose)中运行中心
  • ✅ 您需要隔离服务器依赖关系
  • ✅ 您想使用注册表中的预构建MCP服务器映像

在以下情况下选择stdio传输:

  • ✅ 您正在本地开发,并希望更快的迭代
  • ✅ 运行时依赖项已安装
  • ✅ 您需要绝对最低的延迟

在以下情况下选择HTTP传输:

  • ✅ MCP服务器远程托管
  • ✅ 您需要独立扩展服务器
  • ✅ 您想使用托管MCP服务器服务

示例:完成Docker设置

以下是在Docker中运行多个MCP服务器的完整示例:

# 1. Build your custom MCP server image
docker build -t my-mcp-server:v1.0 ./my-server

# 2. Create Docker network for inter-container communication
docker network create mcp-network

# 3. Configure servers
cat > config.json << 'JSON'
{
  "mcpServers": {
    "echo": {
      "image": "mcp-echo:latest"
    },
    "custom-tools": {
      "image": "my-mcp-server:v1.0",
      "env": {
        "API_KEY": "${MY_API_KEY}"
      },
      "volumes": {
        "/host/data": "/data"
      }
    }
  }
}
JSON

# 4. Run the hub
MY_API_KEY=secret123 ./mcp-hub --config config.json

此设置为您提供:

  • ✨ 对集线器主机没有运行时依赖关系
  • ✨ 每个MCP服务器的隔离环境
  • ✨ 通过更改Docker镜像标签轻松更新
  • ✨ 可重复部署

容器化部署

mcp-hub本身可以在Docker容器中运行。看 DOCKER_DEPLOYMENT.md 获取完整的部署指南。

快速部署Docker

# Build the image
docker build -t mcp-hub:latest .

# Run with your config
docker run -d \
  --name mcp-hub \
  -p 8080:8080 \
  -v $(pwd)/config.json:/app/config.json:ro \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e GITHUB_TOKEN=${GITHUB_TOKEN} \
  mcp-hub:latest

或者使用Docker Compose

docker-compose up -d

图像大小:

  • 标准(使用Docker CLI):~47MB
  • 最小(仅限stdio/HTTP):~6MB

环境变量会自动在配置中传递和扩展。

配置文件监视

MCP Hub会自动监视配置文件的更改,并相应地更新注册表。修改时 config.json,该中心将:

  • 添加新服务器:自动启动任何新添加的MCP服务器
  • 删除服务器:停止从配置中删除或禁用的服务器
  • 重新加载服务器:重新启动配置已更改的服务器
  • 更新注册表:保持工具注册表与活动服务器同步

运作原理

观察者使用 fsnotify 监视配置文件中的写入事件。当检测到变化时:

  1. 新配置已加载并验证
  2. 将更改与之前的配置进行比较
  3. 采取适当的行动(启动/停止/重新加载服务器)
  4. 注册表会自动更新
  5. 记录更改以提高可见性

防抖

为了避免处理快速连续的更改(例如,当编辑器多次写入时),观察器包含500ms的去抖动延迟。这可确保在您完成编辑后只重新加载一次配置。

示例

# Start mcp-hub
./mcp-hub --config=config.json

# In another terminal, edit config.json
vim config.json

# The hub will automatically detect changes and log:
# "config file changed, reloading..."
# "adding server: new-server"
# "loaded MCP server: new-server (stdio transport)"

错误处理

如果新配置包含错误:

  • JSON无效:更改被拒绝,hub继续使用之前的配置
  • 缺少必填字段:更改因验证错误而被拒绝
  • 服务器启动失败:记录为警告,其他服务器继续运行