From 3a97119719d8378bccd57ab0830754f75ac01d04 Mon Sep 17 00:00:00 2001 From: samanhappy Date: Wed, 2 Apr 2025 11:16:17 +0800 Subject: [PATCH] docs: update README to enhance feature descriptions and quick start instructions; improve dashboard management details --- README.md | 73 +++++++++++++++++++++++-------------------- assets/dashboard.png | Bin 9218 -> 11383 bytes 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 742360a..cef5df4 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,49 @@ -# MCPHub +# MCPHub: Multiple Servers, Single Endpoint, Zero Hassle MCPHub is a unified hub server that consolidates multiple MCP (Model Context Protocol) servers into a single SSE endpoint. It simplifies service management and provides a centralized interface for all your MCP needs. +![Dashboard Preview](assets/dashboard.png) + ## Features - **Centralized Management**: Manage multiple MCP servers from a single hub - **Protocol Support**: Compatible with stdio and SSE MCP protocols -- **Dashboard UI**: Monitor server status through a web interface -- **Easy Configuration**: Simple JSON-based configuration system +- **Dashboard UI**: Monitor server status and dynamically manage servers through a web interface +- **Dynamic Management**: Add, remove, or reconfigure MCP servers without restarting the hub -## Configuration +## Quick Start -Create a `mcp_settings.json` file in your project root: +### Docker + +```bash +docker run -p 3000:3000 samanhappy/mcphub +``` + +### Dashboard + +Access the interactive management UI at `http://localhost:3000` + +The dashboard provides: + +- Real-time monitoring of all MCP servers +- Status indicators for all connected services +- Dynamic addition or removal of new MCP servers without restarting + +### SSE endpoint + +Connect your Host App, such as Claude Desktop, Cursor, Cherry Studio, and more, seamlessly to `http://localhost:3000/sse`. + +## Local Development + +### Clone the Repository + +```bash +git clone https://github.com/samanhappy/mcphub.git +``` + +### Configuration (Optional) + +Edit the `mcp_settings.json` file: ```json { @@ -28,39 +60,12 @@ Create a `mcp_settings.json` file in your project root: } ``` -## Installation - -### Docker (Recommended) +### Start the Server ```bash -docker run -p 3000:3000 -v $(pwd)/mcp_settings.json:/app/mcp_settings.json samanhappy/mcphub +cd mcphub && pnpm install && pnpm dev ``` -### Manual Installation - -```bash -git clone https://github.com/samanhappy/mcphub.git -cd mcphub -pnpm install -pnpm dev -``` - -## Usage - -### Dashboard -Access the monitoring UI at `http://localhost:3000` - -![Dashboard Preview](assets/dashboard.png) - -### API Endpoint -Connect your applications to `http://localhost:3000/sse` - - -## Requirements - -- Node.js 14+ (for manual installation) -- Docker (for containerized deployment) - ## License [MIT License](LICENSE) diff --git a/assets/dashboard.png b/assets/dashboard.png index 1a1bf6f0a5b5f9a7e2a506137413473de8d76600..8c3c8a0be892565620b16f6b5055f4a2ca060de3 100644 GIT binary patch literal 11383 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 literal 9218 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