-
Notifications
You must be signed in to change notification settings - Fork 8
Open
Description
Issue Details
Problem Description
The HttpSseFilterChainFactory had hardcoded values for HTTP path and host, making it impossible to:
- Connect to different endpoints: All clients were forced to use
/rpcpath, but MCP servers may use/sse,/events,/api/mcp, etc. - Specify actual server host: The host was hardcoded to
localhost, preventing connections to remote MCP servers - Configure per-connection settings: Each factory instance couldn't be customized for different server configurations
Root Cause
The factory constructor only accepted three parameters:
HttpSseFilterChainFactory(event::Dispatcher& dispatcher,
McpProtocolCallbacks& message_callbacks,
bool is_server = true)The http_path and http_host values used by the internal filters were either:
- Hardcoded as
/rpcandlocalhost - Not passed through from the factory to the filter chain
Technical Flow (Before Fix)
// User wants to connect to https://mcp.example.com/api/sse
auto factory = std::make_shared<HttpSseFilterChainFactory>(
dispatcher, callbacks, false /* client mode */);
// Factory creates filters with hardcoded values:
// - http_path_ = "/rpc" ❌ Should be "/api/sse"
// - http_host_ = "localhost" ❌ Should be "mcp.example.com"
// Result: Client sends request to wrong endpoint
// GET /rpc HTTP/1.1
// Host: localhostTechnical Flow (After Fix)
// User wants to connect to https://mcp.example.com/api/sse
auto factory = std::make_shared<HttpSseFilterChainFactory>(
dispatcher, callbacks,
false, // client mode
"/api/sse", // custom path ✅
"mcp.example.com"); // custom host ✅
// Factory creates filters with configured values
// Result: Client sends correct request
// GET /api/sse HTTP/1.1
// Host: mcp.example.comHow to Reproduce
Prerequisites
- gopher-mcp client code
- An MCP server running on a non-default endpoint
Steps to Reproduce
1. Create factory for remote MCP server:
#include "mcp/filter/http_sse_filter_chain_factory.h"
// Before fix: No way to specify path/host
auto factory = std::make_shared<HttpSseFilterChainFactory>(
dispatcher, callbacks, false /* client mode */);
// Path is hardcoded to "/rpc"
// Host is hardcoded to "localhost"2. Attempt to connect to server at different endpoint:
// Server is at: https://mcp.example.com:8080/api/events
// But factory will send requests to: /rpc on localhost3. Observe the failure:
Expected HTTP Request:
GET /api/events HTTP/1.1
Host: mcp.example.com:8080
Actual HTTP Request:
GET /rpc HTTP/1.1
Host: localhost
Result: Connection fails or connects to wrong server
Minimal Reproduction Test
TEST(HttpSseFilterChainFactory, CannotConfigureEndpoint) {
MockMcpCallbacks callbacks;
auto dispatcher = createDispatcher();
// Before fix: Constructor doesn't accept path/host
// This would fail to compile or use wrong defaults
auto factory = std::make_shared<HttpSseFilterChainFactory>(
*dispatcher, callbacks, false, "/sse", "server.example.com:8080");
// Before fix: Compilation error - constructor only takes 3 params
// After fix: Compiles and uses custom path/host
}
TEST(HttpSseFilterChainFactory, DefaultsToWrongEndpoint) {
MockMcpCallbacks callbacks;
auto dispatcher = createDispatcher();
auto factory = std::make_shared<HttpSseFilterChainFactory>(
*dispatcher, callbacks, false);
// Create filter chain and inspect HTTP requests
// Before fix: Uses /rpc and localhost regardless of server
// After fix: Uses configurable defaults, can be overridden
}Key Changes in the Fix
| Component | Change |
|---|---|
| Constructor signature | Added http_path and http_host parameters with defaults |
| Member variables | Added http_path_ and http_host_ storage |
| Include directive | Added <string> for std::string member types |
| Default values | http_path="/rpc", http_host="localhost" for backward compatibility |
Updated Constructor
// Before
HttpSseFilterChainFactory(event::Dispatcher& dispatcher,
McpProtocolCallbacks& message_callbacks,
bool is_server = true)
// After
HttpSseFilterChainFactory(event::Dispatcher& dispatcher,
McpProtocolCallbacks& message_callbacks,
bool is_server = true,
const std::string& http_path = "/rpc",
const std::string& http_host = "localhost")Usage Examples
// Server mode with defaults
auto server_factory = std::make_shared<HttpSseFilterChainFactory>(
dispatcher, callbacks, true);
// Client mode for Claude Desktop MCP
auto claude_factory = std::make_shared<HttpSseFilterChainFactory>(
dispatcher, callbacks, false, "/sse", "localhost:3000");
// Client mode for remote MCP server
auto remote_factory = std::make_shared<HttpSseFilterChainFactory>(
dispatcher, callbacks, false, "/api/events", "mcp.example.com:8080");
// Client mode for custom enterprise MCP
auto enterprise_factory = std::make_shared<HttpSseFilterChainFactory>(
dispatcher, callbacks, false, "/v2/mcp/stream", "internal.corp.com:443");Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels