A central proxy server that aggregates multiple upstream MCP (Model Context Protocol) servers, providing a unified interface for downstream clients using the official @modelcontextprotocol/sdk
.
- Streamable HTTP Protocol: Uses official MCP SDK with streamable-http transport for reliable client connections
- Capability Aggregation: Automatically discovers and aggregates tools, resources, and prompts from upstream servers
- Transparent Routing: Routes requests to appropriate upstream servers based on prefixed capability names (
serverName___toolName
) - Multiple Client Support: Serves multiple downstream clients simultaneously via HTTP sessions with automatic cleanup
- Automatic Reconnection: Handles upstream server disconnections with automatic retry and exponential backoff
- Real-time Updates: Live capability updates as upstream servers connect/disconnect
- Fast Startup Mode: Server starts immediately while upstream connections initialize in background
- Dynamic Configuration: Hot-reload configuration changes without restarting the server
- Session Management: 30-minute session timeout with automatic cleanup of inactive sessions
┌─────────────┐ ┌─────────────────┐ ┌─────────────┐
│ Downstream │ │ │ │ Upstream │
│ Client │◄──►│ 1mcp │◄──►│ Server │
│ (HTTP/MCP) │ │ (streamable- │ │ (stdio/sse/ │
└─────────────┘ │ http server) │ │ streamable) │
│ ┌──────────────┤ └─────────────┘
┌─────────────┐ │ │ Capability │ ┌─────────────┐
│ Downstream │ │ │ Registry │ │ Upstream │
│ Client │◄──►│ │ │◄──►│ Server │
│ (HTTP/MCP) │ │ │ │ │ (stdio/sse/ │
└─────────────┘ │ ├──────────────┤ │ streamable) │
│ │ Request │ └─────────────┘
┌─────────────┐ │ │ Router │ ┌─────────────┐
│ Downstream │ │ │ │ │ Upstream │
│ Client │◄──►│ │ Session │ │ Server │
│ (HTTP/MCP) │ │ │ Manager │◄──►│ (stdio/sse/ │
└─────────────┘ │ │ │ │ streamable) │
│ └──────────────┤ └─────────────┘
│ │ Config │ ┌─────────────┐
│ │ Watcher │ │ Upstream │
│ │ │ │ Server │
│ │ │◄──►│ (stdio/sse/ │
│ └──────────────┤ │ streamable) │
└─────────────────┘ └─────────────┘
- Node.js 18+
- npm or yarn
- Clone and install dependencies:
git clone <repository-url>
cd 1mcp
npm install
- Build the project:
npm run build
- Create configuration file:
cp config/mcp_servers.json.example config/mcp_servers.json
Edit config/mcp_servers.json
to configure your upstream servers:
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest"]
},
"crawl4ai": {
"type": "sse",
"url": "http://localhost:11235/mcp/sse"
},
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/directory"]
},
"streamable-server": {
"type": "streamable-http",
"url": "http://127.0.0.1:12306/mcp"
}
}
}
1mcp supports hot-reloading of configuration changes. You can add, remove, or modify upstream servers without restarting the server:
- Add a new server: Simply add a new entry to
mcp_servers.json
and save the file - Remove a server: Delete the server entry from the configuration file
- Update server config: Modify any server configuration and save
The server will automatically:
- ✅ Detect configuration changes
- ✅ Connect to new servers
- ✅ Remove disconnected servers
- ✅ Update existing server configurations
- ✅ Notify connected clients of capability changes
Example: Add a new server while 1mcp is running:
{
"mcpServers": {
"existing-server": { ... },
"new-server": {
"type": "stdio",
"command": "npx",
"args": ["@new/mcp-server"]
}
}
}
After saving the file, you'll see:
📝 Configuration file changed: /path/to/config/mcp_servers.json
🔄 Configuration file changed, updating upstream connections...
📋 Configuration changes detected:
➕ Servers to add: 1
➖ Servers to remove: 0
🔄 Servers to update: 0
➕ Adding new server: new-server
✅ Added server: new-server
📊 Configuration update complete (1234ms):
✅ Removed: 0 servers
✅ Updated: 0 servers
✅ Added: 1 servers
❌ Failed to add: 0 servers
✅ Configuration update completed successfully
1mcp supports all upstream server protocols via their native transports, while providing a unified streamable-http interface to downstream clients.
For servers that communicate via stdin/stdout:
{
"command": "node",
"args": ["server.js"],
"env": {
"DEBUG": "1"
},
"cwd": "/optional/working/directory"
}
For servers using Server-Sent Events:
{
"type": "sse",
"url": "http://localhost:8080/mcp/sse",
"headers": {
"Authorization": "Bearer token"
}
}
For servers using streamable HTTP transport:
{
"type": "streamable-http",
"url": "http://localhost:8080/mcp",
"headers": {
"X-API-Key": "your-key"
}
}
The system can automatically detect transport type:
{
"type": "auto",
"url": "http://localhost:8080/mcp"
}
Start the 1mcp server:
npm start
# or
node dist/main.js
The server provides fast startup mode - it starts immediately on port 3000 while upstream connections initialize in the background.
Usage: node dist/main.js [options]
Options:
--port=<number> Server port (default: 3000)
--host=<string> Server host (default: localhost)
--no-cors Disable CORS (default: enabled)
--config=<path> Configuration file path (default: config/mcp_servers.json)
--help, -h Show this help message
Examples:
node dist/main.js # Start with default settings
node dist/main.js --port=8080 --host=0.0.0.0 # Custom port and host
node dist/main.js --config=./custom-config.json # Custom config file
node dist/main.js --port=3001 --no-cors # Custom port, no CORS
When the server starts, it provides these endpoints:
POST /mcp
- Main MCP protocol endpoint (streamable-http)GET /health
- Health check and statisticsGET /mcp/info
- Server information and capabilities
- Connection: 1mcp connects to each configured upstream server using their native protocols
- Discovery: Calls
tools/list
,resources/list
, andprompts/list
on each server - Registration: Registers capabilities with server name prefix (e.g.,
serverName___toolName
) - Serving: Provides aggregated capabilities to downstream clients via streamable-http
- Prefix Parsing: Extracts server name from prefixed capability name using
___
separator - Validation: Verifies capability exists and server is connected
- Forwarding: Removes prefix and forwards request to upstream server
- Response: Returns upstream response to downstream client
- File Watching: Monitors
mcp_servers.json
for changes using Node.js file watcher - Change Detection: Detects additions, removals, and modifications to server configurations
- Connection Management: Automatically connects to new servers and disconnects from removed ones
- Capability Updates: Re-registers capabilities when servers are added/removed
- Client Notification: Notifies connected clients of capability changes via
listChanged
events
- Each client connection gets a unique session ID
- Sessions persist indefinitely (no timeout or cleanup)
- Session state maintained in memory with connection pooling
- Streamable HTTP transport provides reliable bidirectional communication
// Client requests tool: "playwright___click"
{
"id": 1,
"method": "tools/call",
"params": {
"name": "playwright___click",
"arguments": { "selector": "#button" }
}
}
// 1mcp routes to "playwright" server with original name "click"
{
"id": 1,
"method": "tools/call",
"params": {
"name": "click",
"arguments": { "selector": "#button" }
}
}
GET /health
Returns server status, statistics, and connection information:
{
"status": "healthy",
"timestamp": "2024-01-01T00:00:00.000Z",
"stats": {
"totalTools": 15,
"totalResources": 5,
"totalPrompts": 3,
"connectedServers": 4,
"upstreamServers": ["playwright", "filesystem", "crawl4ai"]
},
"transport": "streamable-http",
"port": 3000
}
GET /mcp/info
Returns server capabilities and endpoint information:
{
"name": "1mcp",
"version": "1.0.0",
"transport": "streamable-http",
"capabilities": {
"totalTools": 15,
"totalResources": 5,
"totalPrompts": 3
},
"endpoints": {
"mcp": "/mcp",
"health": "/health",
"info": "/mcp/info",
"session-info": "/mcp/session-info"
}
}
POST /mcp
Content-Type: application/json
mcp-session-id: <session-id>
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
The server uses streamable-http transport with session management. Each client connection gets a unique session ID returned in the mcp-session-id
header.
1mcp supports all standard MCP protocol methods:
initialize
- Client initializationtools/list
- List all aggregated toolstools/call
- Call a specific toolresources/list
- List all aggregated resourcesresources/read
- Read a specific resourceprompts/list
- List all aggregated promptsprompts/get
- Get a specific prompt
src/
├── connectors/ # Upstream server connectors
│ ├── BaseConnector.ts # Abstract base class with common functionality
│ ├── StdioConnector.ts # stdio protocol support
│ ├── SseConnector.ts # SSE protocol support
│ ├── StreamableHttpConnector.ts # streamable-http support
│ └── AutoConnector.ts # Auto-detection connector
├── utils/
│ └── transportDetector.ts # Transport type detection
├── CapabilityRegistry.ts # Tool/resource/prompt registration
├── ConfigLoader.ts # Configuration file handling
├── RequestRouter.ts # Request routing logic (legacy)
├── UpstreamManager.ts # Upstream connection management
├── main.ts # Main entry point with CLI handling
├── McpHubServer.ts # Hub server implementation (alternative)
└── types.ts # TypeScript definitions
npm run build # Compile TypeScript to dist/
npm run dev # Run in development mode with ts-node
npm start # Start the compiled server
npm test # Run Jest tests
npm run lint # Run ESLint
npm run lint:fix # Fix linting issues automatically
npm test
- CapabilityRegistry: Manages registration and lookup of capabilities with prefixing
- UpstreamManager: Handles connection lifecycle, reconnection, and capability discovery
- Connectors: Protocol-specific implementations for different server types
- Session Management: HTTP session handling with automatic cleanup
-
Server not connecting:
- Check server configuration and ensure the upstream server is running
- Verify the server URL is accessible
- Check server logs for detailed error messages
-
Command not found:
- Verify the command path and arguments in configuration
- Ensure the MCP server package is installed
-
Permission denied:
- Check file permissions for stdio servers
- Verify environment variables and working directories
Change the port using command line options:
node dist/main.js --port=8080
Set environment variable for detailed logging:
DEBUG=1mcp:* npm start
- Session timeouts: Sessions automatically expire after 30 minutes of inactivity
- Capability prefixing: All tools/resources are prefixed with
serverName___
- Async initialization: Upstream connections initialize in background after server starts
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Run
npm run lint
andnpm test
- Submit a pull request
- @modelcontextprotocol/sdk: Official MCP SDK for protocol handling
- express: HTTP server framework
- eventsource: SSE client support
MIT License - see LICENSE file for details.