A stateless HTTP proxy service for remote Model Context Protocol (MCP) servers. This service exposes RESTful APIs to interact with MCP tools without requiring direct JSON-RPC communication.
- RESTful API for MCP operations
- Stateless design - no session management required
- Multiple server support - configure multiple MCP servers
- SSE to JSON conversion - automatic handling of Server-Sent Events
- Standard error codes - HTTP-compliant error handling
- Simple configuration - JSON-based server configuration
- Node.js 18.x or higher
- Access to remote MCP servers (HTTP-based)
- Clone or download this repository
- Install dependencies:
npm install- Create your server configuration file:
cp mcp.servers.example.json mcp.servers.json- Edit
mcp.servers.jsonwith your server details:
{
"mcpServers": {
"MyMcpServer": {
"url": "https://your-mcp-server.com/endpoint",
"headers": {
"Authorization": "Bearer your-token-here"
},
"type": "http"
}
}
}The mcp.servers.json file defines all available MCP servers:
mcpServers: Object containing server configurations- Key: Server name (used in API routes)
- Value: Server configuration object
url: MCP server endpoint URLheaders: HTTP headers to include (e.g., authentication)type: Must be"http"for remote servers
Start the server:
npm startFor development with auto-reload:
npm run devThe server will start on http://localhost:8080 (configurable via PORT environment variable).
List all configured MCP servers.
Request:
GET /api/list-serversResponse:
{
"servers": [
{
"name": "MyMcpServer",
"url": "https://your-mcp-server.com/endpoint",
"type": "http"
}
],
"count": 1
}Initialize connection with an MCP server and retrieve server capabilities. The server may return a session ID that must be used in subsequent requests.
Request:
POST /api/mcp/{server_name}/initializeResponse:
{
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {
"listChanged": true
}
},
"serverInfo": {
"name": "example-server",
"version": "1.0.0"
},
"sessionId": "abc123-session-id-xyz"
}Response Headers:
Mcp-Session-Id: abc123-session-id-xyz
Note: Save the sessionId from the response to use in subsequent requests. Some servers (like GitHub MCP) require it.
Get all available tools from an MCP server.
Request:
GET /api/mcp/{server_name}/tools?init=falseOptional query parameters:
cursor: Pagination cursor from previous responseinit: Initialize session before listing tools (default:false)true: Initialize connection firstfalse: Skip initialization (assumes session already initialized)
sessionId: MCP session ID from initialization (alternative to header)
Optional headers:
Mcp-Session-Id: MCP session ID from initialization
Response:
{
"tools": [
{
"name": "get_weather",
"description": "Get current weather for a location",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name"
}
},
"required": ["location"]
}
}
],
"nextCursor": "optional-cursor-for-next-page"
}Execute a specific tool with provided arguments.
Request:
POST /api/mcp/{server_name}/tools/{tool_name}/execute?init=false
Content-Type: application/json
{
"location": "San Francisco",
"units": "celsius"
}Optional query parameters:
init: Initialize session before executing tool (default:false)true: Initialize connection firstfalse: Skip initialization (assumes session already initialized)
sessionId: MCP session ID from initialization (alternative to header)
Optional headers:
Mcp-Session-Id: MCP session ID from initialization
Response:
{
"content": [
{
"type": "text",
"text": "Temperature: 22°C, Conditions: Sunny"
}
],
"isError": false
}The service returns standard HTTP error codes:
- 400 Bad Request: Invalid request format
- 401 Unauthorized: Authentication failed
- 404 Not Found: Server or tool not found
- 500 Internal Server Error: Server error or MCP communication failure
Error response format:
{
"error": "Error type",
"message": "Detailed error message"
}List servers:
curl http://localhost:8080/api/list-serversInitialize a server and get session ID:
# Initialize and capture session ID
RESPONSE=$(curl -i -X POST http://localhost:8080/api/mcp/MyMcpServer/initialize)
SESSION_ID=$(echo "$RESPONSE" | grep -i "mcp-session-id:" | cut -d' ' -f2 | tr -d '\r')Using session ID in subsequent requests:
Via query parameter:
curl "http://localhost:8080/api/mcp/MyMcpServer/tools?sessionId=$SESSION_ID"Via header (recommended):
curl http://localhost:8080/api/mcp/MyMcpServer/tools \
-H "Mcp-Session-Id: $SESSION_ID"Execute a tool with session ID:
curl -X POST http://localhost:8080/api/mcp/MyMcpServer/tools/get_weather/execute \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: $SESSION_ID" \
-d '{"location": "San Francisco"}'One-shot request (init + execute in single call):
curl -X POST "http://localhost:8080/api/mcp/MyMcpServer/tools/get_weather/execute?init=true" \
-H "Content-Type: application/json" \
-d '{"location": "San Francisco"}'// List tools
const response = await fetch('http://localhost:8080/api/mcp/MyMcpServer/tools');
const { tools } = await response.json();
// Execute a tool
const result = await fetch(
'http://localhost:8080/api/mcp/MyMcpServer/tools/get_weather/execute',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ location: 'San Francisco' })
}
);
const data = await result.json();
console.log(data.content);Each request independently:
- Creates a new MCP client instance
- Optionally initializes connection with the server (controlled by
initquery parameter) - Performs the requested operation
- Returns the result
No session state is maintained between requests.
Session Management:
- Many MCP servers (e.g., GitHub) require session IDs for all requests after initialization
- The
/initializeendpoint returns asessionIdin both the response body andMcp-Session-Idheader - Include the session ID in subsequent requests via:
Mcp-Session-Idheader (recommended)sessionIdquery parameter (alternative)
- Session IDs are server-specific and may expire
Initialization Options:
-
Option 1 (Recommended): Initialize once, reuse session ID
# 1. Initialize SESSION=$(curl -X POST .../initialize | jq -r '.sessionId') # 2. Use session for multiple requests curl .../tools -H "Mcp-Session-Id: $SESSION" curl .../tools/my_tool/execute -H "Mcp-Session-Id: $SESSION" -d '{...}'
-
Option 2: One-shot requests with
init=truecurl ".../tools?init=true" # Initializes and lists tools in one call
-
Option 3: Servers that don't require session IDs
curl .../tools # Works without initialization or session ID
The proxy automatically detects Server-Sent Events (SSE) responses from MCP servers and converts them to standard JSON responses, aggregating all events into a single result.
This proxy implements the Model Context Protocol 2024-11-05 specification, focusing on the tools capability:
- JSON-RPC 2.0 message format
- HTTP+SSE transport layer
- Tool discovery and execution
Configuration file not found:
Error: Configuration file not found
Solution: Create mcp.servers.json from the example file.
Server unreachable:
Error: MCP request failed: fetch failed
Solution: Check the server URL and network connectivity.
Authentication failed:
Error: Authentication failed (401)
Solution: Verify the authorization token in your server configuration.
Tool not found:
Error: Tool not found (404)
Solution: Use the /tools endpoint to list available tools.
Project structure:
mcp-proxy/
├── src/
│ ├── index.js # Express server and routes
│ ├── mcpClient.js # MCP client implementation
│ └── config.js # Configuration loader
├── mcp.servers.json # Server configuration (gitignored)
├── mcp.servers.example.json
├── package.json
└── README.md
MIT
Contributions are welcome! Please ensure:
- Code follows existing style
- All routes are tested
- Error handling is comprehensive
- Documentation is updated