一个用于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: 设置为sse或stream以仅启用相应的传输方式(默认:两者都启用)--endpoint: 如果server设置为sse或stream,此选项设置端点路径(默认:/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传输行为保持不变。
何时使用无状态模式:
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预检请求MCP Proxy提供了灵活的CORS(跨源资源共享)配置,以控制浏览器如何从不同来源访问您的MCP服务器。
默认情况下,CORS启用并具有以下设置:
*(允许所有来源)GET, POST, OPTIONSContent-Type, Authorization, Accept, Mcp-Session-Id, Last-Event-IdtrueMcp-Session-Idimport { 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行为有更多控制,您可以提供详细的配置:
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提供了几个用于创建代理的实用工具。
proxyServer在服务器和客户端之间设置代理。
const transport = new StdioClientTransport();
const client = new Client();
const server = new Server(serverVersion, {
capabilities: {},
});
proxyServer({
server,
client,
capabilities: {},
});
在这个例子中,服务器将代理所有请求到客户端,反之亦然。
startHTTPServer启动一个监听port的代理,并通过StreamableHTTPServerTransport和SSEServerTransport将消息发送到附加的服务器。
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的代理,并将消息发送到附加的sse或streamable服务器。
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);
});
tsx src/bin/mcp-proxy.ts --debug tsx src/fixtures/simple-stdio-server.ts