MCP服务器包装工具

用于包装多个MCP服务器的工具,通过添加服务器名称前缀避免命名冲突,支持多种服务器连接方式和配置选项。

  • by admannon
  • TypeScript
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 admannon/mcp-wrapper

使用说明

mcp包装器

MCP服务器使用服务器名称前缀包装重复的命令和工具,防止使用多个MCP服务器时发生命名冲突。

特性

  • 工具名称前缀:自动在工具名称前加上服务器名称(例如。, serverName__toolName)
  • 多服务器支持:连接到多个底层MCP服务器
  • 透明代理:将工具调用路由到正确的底层服务器
  • 可定制的分离器:配置服务器名称和工具名称之间的分隔符
  • CLI支持:直接通过运行 npx 无需创建包装脚本

安装

npm install mcp-wrapper

用法

CLI用法(不需要脚本文件)

您可以直接通过以下方式运行包装器 npx 无需创建任何脚本文件:

# Using a config file
npx mcp-wrapper --config ./mcp-wrapper.json

# Using inline JSON config
npx mcp-wrapper --config '{"name":"my-wrapper","version":"1.0.0","servers":[{"name":"github","command":"npx","args":["-y","@modelcontextprotocol/server-github"]}]}'

# Using environment variable
export MCP_WRAPPER_CONFIG='{"name":"my-wrapper","version":"1.0.0","servers":[...]}'
npx mcp-wrapper

示例配置文件(mcp-wrapper.json):

{
  "name": "my-wrapper",
  "version": "1.0.0",
  "separator": "__",
  "servers": [
    {
      "name": "github1",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_TOKEN": "token1" }
    },
    {
      "name": "github2",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_TOKEN": "token2" }
    },
    {
      "name": "remote",
      "url": "http://localhost:3000/sse"
    }
  ]
}

程序化使用

import { McpWrapper } from "mcp-wrapper";

const wrapper = new McpWrapper({
  name: "my-wrapper",
  version: "1.0.0",
  servers: [
    {
      name: "github",
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-github"],
      env: { GITHUB_TOKEN: "your-token" },
    },
    {
      name: "filesystem",
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"],
    },
    {
      name: "remote",
      url: "http://localhost:3000/sse",
    },
  ],
  separator: "__", // optional, default is "__"
});

// Connect to all underlying servers
await wrapper.connectToServers();

// Start the wrapper server
await wrapper.start();

配置

包装器是使用 WrapperConfig 对象:

interface WrapperConfig {
  // Name of this wrapper server
  name: string;

  // Version of this wrapper server
  version: string;

  // List of MCP servers to wrap
  servers: WrappedServerConfig[];

  // Separator used between server name and tool name (default: "__")
  separator?: string;
}

interface WrappedServerConfig {
  // Unique prefix name for this server
  name: string;

  // Command to execute to start the MCP server (for stdio transport)
  // Either command or url must be specified, but not both
  command?: string;

  // Arguments to pass to the command (only used with command)
  args?: string[];

  // Environment variables for the server process (only used with command)
  env?: Record<string, string>;

  // Working directory for the server process (only used with command)
  cwd?: string;

  // URL to connect to the MCP server (for SSE transport)
  // Either command or url must be specified, but not both
  url?: string;
}

服务器类型

包装器支持两种类型的MCP服务器连接:

1.基于Stdio的服务器(使用 command)

这些服务器作为子进程启动,并通过stdin/stdout进行通信。这是传统的MCP服务器方法。

{
  "name": "local-server",
  "command": "npx",
  "args": ["-y", "@modelcontextprotocol/server-github"],
  "env": { "GITHUB_TOKEN": "your_token" }
}

2.基于HTTP的服务器(使用 url)

这些服务器是通过HTTP访问的。包装器会自动尝试 流式HTTP (VS Code、Claude和大多数MCP服务器使用的现代MCP协议)首先,然后回落到 上海证券交易所 (传统协议)。可用于连接到远程MCP服务器或在容器中运行的服务器。

{
  "name": "remote-server",
  "url": "http://localhost:3000/mcp"
}

支持的URL示例:

  • https://nuxt.com/mcp -Nuxt的公共MCP服务器(与Streamable HTTP兼容)
  • http://localhost:3000/mcp -您的本地MCP服务器
  • http://localhost:3000/sse -传统SSE端点(自动检测)

重要提示: 这 url 必须指向实际的MCP服务器端点。如果你收到 405 (Method Not Allowed) 或 404 (Not Found) 错误,请验证:

  • URL正确,服务器正在运行
  • 端点实现MCP协议(流式HTTP或SSE)
  • 您正在使用正确的路径(通常以结尾 /mcp, /sse,或类似)

注: 每个服务器必须指定 command 或 url但不是两者都有。您可以在同一包装器配置中混合使用这两种类型的服务器。

示例:与Claude Desktop一起使用

选项1:使用带有配置文件的CLI(推荐-不需要脚本文件)

创建配置文件 ~/.config/mcp-wrapper.json:

{
  "name": "wrapped-servers",
  "version": "1.0.0",
  "servers": [
    {
      "name": "github1",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_TOKEN": "your_token_1" }
    },
    {
      "name": "github2",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_TOKEN": "your_token_2" }
    }
  ]
}

然后添加到Claude Desktop配置:

{
  "mcpServers": {
    "wrapped-servers": {
      "command": "npx",
      "args": ["-y", "mcp-wrapper", "--config", "~/.config/mcp-wrapper.json"]
    }
  }
}

选项2:使用内联JSON配置(根本不需要文件)

{
  "mcpServers": {
    "wrapped-servers": {
      "command": "npx",
      "args": ["-y", "mcp-wrapper", "--config", "{\"name\":\"wrapped\",\"version\":\"1.0.0\",\"servers\":[{\"name\":\"github1\",\"command\":\"npx\",\"args\":[\"-y\",\"@modelcontextprotocol/server-github\"],\"env\":{\"GITHUB_TOKEN\":\"token1\"}},{\"name\":\"github2\",\"command\":\"npx\",\"args\":[\"-y\",\"@modelcontextprotocol/server-github\"],\"env\":{\"GITHUB_TOKEN\":\"token2\"}}]}"]
    }
  }
}

选项3:使用包装脚本

将包装器添加到您的Claude Desktop配置中:

{
  "mcpServers": {
    "wrapped-servers": {
      "command": "node",
      "args": ["/path/to/your/wrapper-script.js"]
    }
  }
}

哪里 wrapper-script.js 包含:

import { McpWrapper } from "mcp-wrapper";

const wrapper = new McpWrapper({
  name: "wrapped-servers",
  version: "1.0.0",
  servers: [
    {
      name: "github1",
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-github"],
      env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN_1 },
    },
    {
      name: "github2",
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-github"],
      env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN_2 },
    },
  ],
});

await wrapper.connectToServers();
await wrapper.start();

注:
上面的脚本示例使用环境变量(GITHUB_TOKEN_1, GITHUB_TOKEN_2)以提供身份验证令牌。
您可以在 env Claude Desktop的MCP服务器配置部分:

{
  "mcpServers": {
    "wrapped-servers": {
      "command": "node",
      "args": ["/path/to/your/wrapper-script.js"],
      "env": {
        "GITHUB_TOKEN_1": "your_token_1",
        "GITHUB_TOKEN_2": "your_token_2"
      }
    }
  }
}

示例:使用VS代码(GitHub Copilot)

选项1:使用带有配置文件的CLI(推荐-不需要脚本文件)

创建配置文件 mcp-wrapper.json 在项目或主目录中,然后创建 .vscode/mcp.json:

{
  "servers": {
    "wrapped-servers": {
      "command": "npx",
      "args": ["-y", "mcp-wrapper", "--config", "/path/to/mcp-wrapper.json"]
    }
  }
}

选项2:使用包装脚本

创建一个 .vscode/mcp.json 工作区中的文件:

{
  "servers": {
    "wrapped-servers": {
      "command": "node",
      "args": ["/path/to/your/wrapper-script.mjs"],
      "env": {
        "GITHUB_TOKEN_1": "your_token_1",
        "GITHUB_TOKEN_2": "your_token_2"
      }
    }
  }
}

哪里 wrapper-script.mjs 包含:

import { McpWrapper } from "mcp-wrapper";

const wrapper = new McpWrapper({
  name: "wrapped-servers",
  version: "1.0.0",
  servers: [
    {
      name: "github1",
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-github"],
      env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN_1 },
    },
    {
      name: "github2",
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-github"],
      env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN_2 },
    },
  ],
});

await wrapper.connectToServers();
await wrapper.start();

或者,您可以在VS代码设置中全局配置MCP服务器(settings.json):

{
  "github.copilot.chat.mcp.servers": {
    "wrapped-servers": {
      "command": "npx",
      "args": ["-y", "mcp-wrapper", "--config", "/path/to/mcp-wrapper.json"]
    }
  }
}

现在,两个GitHub服务器上的工具都可以使用前缀名称:

  • github1__create_issue
  • github1__list_pull_requests
  • github2__create_issue
  • github2__list_pull_requests

故障排除

HTTP连接错误

包装器会自动尝试 流式HTTP (现代协议)首先,然后回到 上海证券交易所 (遗产)如果需要。

HTTP 405(不允许的方法)

Failed to connect to server "xxx": HTTP 405 (Method Not Allowed)

此错误表示URL不支持MCP传输。常见原因:

  • 该URL指向文档页面或网站,而不是MCP服务器
  • 端点未实现MCP协议
  • 你走错路了

解决方案: 验证URL是否指向实际的MCP服务器端点(通常以结尾 /mcp, /sse或类似)。

HTTP 404(未找到)

Failed to connect to server "xxx": HTTP 404 (Not Found)

此错误表示端点不存在。常见原因:

  • URL中的拼写错误
  • 服务器未运行
  • 路径不正确

解决方案: 仔细检查URL,确保MCP服务器正在运行且可访问。

支持的远程服务器

包装器现在支持与VS Code和Claude相同的远程MCP服务器:

  • ✅ https://nuxt.com/mcp -Nuxt的公共MCP服务器(流式HTTP)
  • ✅ 任何实现流式HTTP或SSE传输的MCP服务器
  • ✅ 本地MCP服务器位于 http://localhost:XXXX/mcp

一般连接提示

如果您在连接到远程服务器时遇到问题:

  1. 测试与端点的基本连接(不测试MCP协议): curl http://your-server-url/mcp 对于流式HTTP MCP端点,测试协议支持: curl -X POST http://your-server-url/mcp
  2. 检查URL是否正确,是否包含正确的路径
  3. 确保您的网络允许出站HTTP/HTTPS连接
  4. 对于本地服务器,请确保使用正确的主机和端口

错误处理和弹性

包装器旨在对服务器连接故障具有弹性:

故障弱化

如果一个或多个子服务器无法连接:

  • 包装将 继续启动 已成功连接的服务器
  • 失败的连接会记录到stderr,并显示详细的错误消息
  • 成功连接的服务器上的工具仍然可用
  • 包装器可以与配置的服务器子集一起运行

这确保了:

  • 单个配置错误或不可用的服务器不会阻止包装器启动
  • 客户端(如Google Antigravity、Claude Desktop、VS Code)可以成功初始化
  • 您可以清楚地看到哪些服务器正在工作,哪些服务器发生了故障

连接超时

每个子服务器连接都有一个 30秒超时 以防止包装器在无响应的服务器上无限期挂起。如果服务器在此时间内没有响应,则连接将中止,包装器将继续与其他服务器连接。

示例场景

场景1:一台服务器失败,其他服务器成功

Failed to connect to server "unavailable": Error: spawn ENOENT
Skipping server "unavailable", will continue with remaining servers
Connected to server "github" with 15 tools
Connected to server "filesystem" with 8 tools
Successfully connected to 2 server(s)
Failed to connect to 1 server(s): unavailable

场景2:所有服务器都出现故障

Failed to connect to server "server1": Error: spawn ENOENT
Skipping server "server1", will continue with remaining servers
Failed to connect to server "server2": Connection timeout after 30000ms
Skipping server "server2", will continue with remaining servers
Successfully connected to 0 server(s)
Failed to connect to 2 server(s): server1, server2

即使在场景2中,包装器也会成功启动(使用0个工具)而不是崩溃,从而允许客户端完成初始化并收到明确的错误消息。

API

McpWrapper

用于创建包装服务器的主类。

构造函数

new McpWrapper(config: WrapperConfig)

方法

  • connectToServers(): Promise<void> -连接到所有已配置的底层MCP服务器
  • start(): Promise<void> -使用stdio传输启动包装服务器
  • close(): Promise<void> -关闭所有连接并停止服务器
  • getWrappedTools(): Array<WrappedToolInfo> -返回有关所有包装工具的信息

工具函数

// Create a prefixed tool name
prefixToolName(serverName: string, toolName: string, separator?: string): string

// Parse a prefixed tool name
parseToolName(prefixedName: string, separator?: string): { serverName: string; originalName: string } | null

// Validate server name (doesn't contain separator)
isValidServerName(serverName: string, separator?: string): boolean

// Validate tool name (doesn't contain separator)
isValidToolName(toolName: string, separator?: string): boolean

许可证

阿帕奇-2.0