返回市场
MCP代理服务器

MCP代理服务器

作者:punkpeye209 星标更新:2025-11-24

项目介绍

MCP Proxy

一个用于MCP服务器的可流式传输的HTTP和SSE代理,这些服务器使用stdio传输。

[!NOTE] 默认情况下启用CORS,并且可以配置选项。详情见CORS配置

[!NOTE] 对于Python实现,请参阅mcp-proxy

[!NOTE] FastMCP(FastMCP)使用的正是MCP Proxy来支持流式传输的HTTP和SSE。

安装

npm install mcp-proxy

快速开始

命令行

npx mcp-proxy --port 8080 --shell tsx server.js

这会启动一个服务器和stdio服务器(tsx server.js)。该服务器监听8080端口以及/mcp(流式传输HTTP)和/sse(SSE)端点,并将消息转发到stdio服务器。

选项:

  • --server: 设置为ssestream以仅启用相应的传输方式(默认:两者都启用)
  • --endpoint: 如果server设置为ssestream,此选项设置端点路径(默认:/sse/mcp
  • --sseEndpoint: 设置SSE端点路径(默认:/sse)。如果server设置为sse,则覆盖--endpoint
  • --streamEndpoint: 设置流式传输HTTP端点路径(默认:/mcp)。如果server设置为stream,则覆盖--endpoint
  • --stateless: 启用无状态模式的HTTP流式传输(不进行会话管理)。在这种模式下,每个请求都会创建一个新的服务器实例,而不是维持持久会话。
  • --port: 指定要监听的端口(默认:8080)
  • --requestTimeout: 请求到MCP服务器的超时时间(毫秒,默认:300000,即5分钟)
  • --debug: 启用调试日志
  • --shell: 通过用户的shell启动服务器
  • --apiKey: 验证请求的API密钥(使用X-API-Key头部)

将参数传递给被包装的命令

当包装一个接受以-开头参数的命令时,必须使用--来防止mcp-proxy将其解释为自己的选项。--之后的所有内容都会直接传递给被包装的命令。

例如,要包装一个使用-v标志的命令:

# 错误:mcp-proxy会尝试解析-v作为其自身的选项
npx mcp-proxy --port 8080 my-command -v

# 正确:使用--将-v传递给my-command
npx mcp-proxy --port 8080 -- my-command -v

无状态模式

默认情况下,MCP Proxy为HTTP流式传输维持持久会话,其中每个客户端连接都与一个在会话期间保持存活的服务器实例相关联。

无状态模式(--stateless)改变了这种行为:

  • 无会话管理:每个请求都会创建一个新的服务器实例,而不是维持持久会话
  • 简化部署:适用于无服务器环境或希望最小化内存使用的情况
  • 请求隔离:每个请求都是完全独立的,对于某些用途可能有益

示例用法:

# 启用无状态模式
npx mcp-proxy --port 8080 --stateless tsx server.js

# 仅启用流式传输的无状态模式
npx mcp-proxy --port 8080 --stateless --server stream tsx server.js

[!NOTE] 无状态模式仅影响HTTP流式传输(/mcp端点)。SSE传输行为保持不变。

何时使用无状态模式:

  • 无服务器环境:当部署到AWS Lambda、Vercel等平台时
  • 负载均衡:当需要将请求分布到多个实例时
  • 内存优化:当希望最小化服务器内存使用时
  • 请求隔离:当需要请求之间完全独立时
  • 简单部署:当不需要维护连接状态时

API密钥认证

MCP Proxy支持可选的API密钥认证来保护您的端点。启用后,客户端必须在X-API-Key头部提供有效的API密钥才能访问代理。

启用认证

为了向后兼容,默认情况下禁用认证。要启用它,可以通过以下方式提供API密钥:

命令行:

npx mcp-proxy --port 8080 --apiKey "your-secret-key" tsx server.js

环境变量:

export MCP_PROXY_API_KEY="your-secret-key"
npx mcp-proxy --port  8080 tsx server.js

客户端配置

客户端必须在X-API-Key头部包含API密钥:

// 对于流式传输HTTP传输
const transport = new StreamableHTTPClientTransport(
  new URL('http://localhost:8080/mcp'),
  {
    headers: {
      'X-API-Key': 'your-secret-key'
    }
  }
);

// 对于SSE传输
const transport = new SSEClientTransport(
  new URL('http://localhost:8080/sse'),
  {
    headers: {
      'X-API-Key': 'your-secret-key'
    }
  }
);

免认证端点

以下端点不需要认证:

  • /ping - 健康检查端点
  • OPTIONS请求 - CORS预检请求

安全注意事项

  • 生产中使用HTTPS:API密钥应仅通过安全连接传输
  • 确保密钥安全:切勿将API密钥提交到版本控制
  • 生成强密钥:使用加密安全的随机字符串作为API密钥
  • 定期轮换密钥:定期更改API密钥以提高安全性

CORS配置

MCP Proxy提供了灵活的CORS(跨源资源共享)配置,以控制浏览器如何从不同来源访问您的MCP服务器。

默认行为

默认情况下,CORS启用并具有以下设置:

  • 来源*(允许所有来源)
  • 方法GET, POST, OPTIONS
  • 头部Content-Type, Authorization, Accept, Mcp-Session-Id, Last-Event-Id
  • 凭据true
  • 暴露头部Mcp-Session-Id

基本配置

import { startHTTPServer } from 'mcp-proxy';

// 使用默认CORS设置(向后兼容)
await startHTTPServer({
  createServer: async () => { /* ... */ },
  port: 3000,
});

// 显式启用默认CORS
await startHTTPServer({
  createServer: async () => { /* ... */ },
  port: 3000,
  cors: true,
});

// 完全禁用CORS
await startHTTPServer({
  createServer: async () => { /* ... */ },
  port: 3000,
  cors: false,
});

高级CORS配置

为了对CORS行为有更多控制,您可以提供详细的配置:

import { startHTTPServer, CorsOptions } from 'mcp-proxy';

const corsOptions: CorsOptions = {
  // 允许特定来源
  origin: ['https://app.example.com', 'https://admin.example.com'],
  
  // 或使用函数进行动态来源验证
  origin: (origin: string) => origin.endsWith('.example.com'),
  
  // 指定允许的方法
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  
  // 允许任何头部(对于具有自定义头部的浏览器客户端有用)
  allowedHeaders: '*',
  
  // 或指定确切的头部
  allowedHeaders: [
    'Content-Type',
    'Authorization',
    'Accept',
    'Mcp-Session-Id',
    'Last-Event-Id',
    'X-Custom-Header',
    'X-API-Key'
  ],
  
  // 要暴露给客户端的头部
  exposedHeaders: ['Mcp-Session-Id', 'X-Total-Count'],
  
  // 允许凭据
  credentials: true,
  
  // 缓存预检请求24小时
  maxAge: 86400,
};

await startHTTPServer({
  createServer: async () => { /* ... */ },
  port: 3000,
  cors: corsOptions,
});

常见用例

允许任何自定义头部(解决浏览器CORS问题):

await startHTTPServer({
  createServer: async () => { /* ... */ },
  port: 3000,
  cors: {
    allowedHeaders: '*', // 允许X-Custom-Header, X-API-Key等
  },
});

限制到特定域:

await startHTTPServer({
  createServer: async () => { /* ... */ },
  port: 3000,
  cors: {
    origin: ['https://myapp.com', 'https://admin.myapp.com'],
    allowedHeaders: '*',
  },
});

开发友好设置:

await startHTTPServer({
  createServer: async () => { /* ... */ },
  port: 3000,
  cors: {
    origin: ['http://localhost:3000', 'http://localhost:5173'], // 常见开发端口
    allowedHeaders: '*',
    credentials: true,
  },
});

从旧版本迁移

如果您正在使用mcp-proxy 5.5.6并且想要在5.9.0+中获得相同的行为:

// 旧行为(5.5.6)- 自动通配符头部
await startHTTPServer({
  createServer: async () => { /* ... */ },
  port: 3000,
});

// 新等效行为(5.9.0+)- 显式通配符头部
await startHTTPServer({
  createServer: async () => { /* ... */ },
  port: 3000,
  cors: {
    allowedHeaders: '*',
  },
});

Node.js SDK

Node.js SDK提供了几个用于创建代理的实用工具。

proxyServer

在服务器和客户端之间设置代理。

const transport = new StdioClientTransport();
const client = new Client();

const server = new Server(serverVersion, {
  capabilities: {},
});

proxyServer({
  server,
  client,
  capabilities: {},
});

在这个例子中,服务器将代理所有请求到客户端,反之亦然。

startHTTPServer

启动一个监听port的代理,并通过StreamableHTTPServerTransportSSEServerTransport将消息发送到附加的服务器。

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { startHTTPServer } from "mcp-proxy";

const { close } = await startHTTPServer({
  createServer: async () => {
    return new Server();
  },
  eventStore: new InMemoryEventStore(),
  port: 8080,
  stateless: false, // 可选:启用HTTP流式传输的无状态模式
});

close();

选项:

  • createServer: 创建新服务器实例的函数,针对每个连接
  • eventStore: 流式传输HTTP传输的事件存储(可选)
  • port: 监听的端口号
  • host: 绑定的主机(默认:::
  • sseEndpoint: SSE端点路径(默认:/sse,设置为null以禁用)
  • streamEndpoint: 流式传输HTTP端点路径(默认:/mcp,设置为null以禁用)
  • stateless: 启用HTTP流式传输的无状态模式(默认:false)
  • apiKey: 验证请求的API密钥(可选)
  • cors: CORS配置(默认:启用宽松设置,参见CORS配置部分)
  • onConnect: 服务器连接时的回调(可选)
  • onClose: 服务器断开时的回调(可选)
  • onUnhandledRequest: 未处理的HTTP请求的回调(可选)

startStdioServer

启动一个监听stdio的代理,并将消息发送到附加的ssestreamable服务器。

import { ServerType, startStdioServer } from "./startStdioServer.js";

await startStdioServer({
  serverType: ServerType.SSE,
  url: "http://127.0.0.1:8080/sse",
});

tapTransport

监听传输并记录事件。

import { tapTransport } from "mcp-proxy";

const transport = tapTransport(new StdioClientTransport(), (event) => {
  console.log(event);
});

开发

使用本地服务器运行MCP Proxy

tsx src/bin/mcp-proxy.ts --debug tsx src/fixtures/simple-stdio-server.ts