@samanhappy/mcphub 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +170 -0
- package/README.zh.md +173 -0
- package/bin/mcphub.js +54 -0
- package/dist/config/index.js +41 -0
- package/dist/config/index.js.map +1 -0
- package/dist/controllers/authController.js +149 -0
- package/dist/controllers/authController.js.map +1 -0
- package/dist/controllers/groupController.js +312 -0
- package/dist/controllers/groupController.js.map +1 -0
- package/dist/controllers/marketController.js +140 -0
- package/dist/controllers/marketController.js.map +1 -0
- package/dist/controllers/serverController.js +283 -0
- package/dist/controllers/serverController.js.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/middlewares/auth.js +24 -0
- package/dist/middlewares/auth.js.map +1 -0
- package/dist/middlewares/index.js +33 -0
- package/dist/middlewares/index.js.map +1 -0
- package/dist/models/User.js +80 -0
- package/dist/models/User.js.map +1 -0
- package/dist/routes/index.js +56 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/server.js +58 -0
- package/dist/server.js.map +1 -0
- package/dist/services/groupService.js +189 -0
- package/dist/services/groupService.js.map +1 -0
- package/dist/services/marketService.js +98 -0
- package/dist/services/marketService.js.map +1 -0
- package/dist/services/mcpService.js +333 -0
- package/dist/services/mcpService.js.map +1 -0
- package/dist/services/sseService.js +103 -0
- package/dist/services/sseService.js.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/migration.js +47 -0
- package/dist/utils/migration.js.map +1 -0
- package/package.json +92 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# MCPHub: Your Ultimate MCP Server Hub
|
|
2
|
+
|
|
3
|
+
English | [中文版](README.zh.md)
|
|
4
|
+
|
|
5
|
+
MCPHub is a unified management platform that aggregates multiple MCP (Model Context Protocol) servers into separate SSE endpoints for different scenarios by group. It streamlines your AI tool integrations through an intuitive interface and robust protocol handling.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## 🚀 Features
|
|
10
|
+
|
|
11
|
+
- **Out-of-the-Box MCP Server Support**: Seamlessly integrate popular servers like `amap-maps`, `playwright`, `fetch`, `slack`, and more.
|
|
12
|
+
- **Centralized Dashboard**: Monitor real-time status and performance metrics from one sleek web UI.
|
|
13
|
+
- **Flexible Protocol Handling**: Full compatibility with both stdio and SSE MCP protocols.
|
|
14
|
+
- **Hot-Swappable Configuration**: Add, remove, or update MCP servers on the fly — no downtime required.
|
|
15
|
+
- **Group-Based Access Control**: Organize servers into customizable groups for streamlined permissions management.
|
|
16
|
+
- **Secure Authentication**: Built-in user management with role-based access powered by JWT and bcrypt.
|
|
17
|
+
- **Docker-Ready**: Deploy instantly with our containerized setup.
|
|
18
|
+
|
|
19
|
+
## 🔧 Quick Start
|
|
20
|
+
|
|
21
|
+
### Optional Configuration
|
|
22
|
+
|
|
23
|
+
Create a `mcp_settings.json` file to customize your server settings:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"mcpServers": {
|
|
28
|
+
"amap": {
|
|
29
|
+
"command": "npx",
|
|
30
|
+
"args": ["-y", "@amap/amap-maps-mcp-server"],
|
|
31
|
+
"env": {
|
|
32
|
+
"AMAP_MAPS_API_KEY": "your-api-key"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"playwright": {
|
|
36
|
+
"command": "npx",
|
|
37
|
+
"args": ["@playwright/mcp@latest", "--headless"]
|
|
38
|
+
},
|
|
39
|
+
"fetch": {
|
|
40
|
+
"command": "uvx",
|
|
41
|
+
"args": ["mcp-server-fetch"]
|
|
42
|
+
},
|
|
43
|
+
"slack": {
|
|
44
|
+
"command": "npx",
|
|
45
|
+
"args": ["-y", "@modelcontextprotocol/server-slack"],
|
|
46
|
+
"env": {
|
|
47
|
+
"SLACK_BOT_TOKEN": "your-bot-token",
|
|
48
|
+
"SLACK_TEAM_ID": "your-team-id"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"users": [
|
|
53
|
+
{
|
|
54
|
+
"username": "admin",
|
|
55
|
+
"password": "$2b$10$Vt7krIvjNgyN67LXqly0uOcTpN0LI55cYRbcKC71pUDAP0nJ7RPa.",
|
|
56
|
+
"isAdmin": true
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
> **Note**: Default credentials are `admin` / `admin123`. Passwords are securely hashed with bcrypt. Generate a new hash with:
|
|
63
|
+
>
|
|
64
|
+
> ```bash
|
|
65
|
+
> npx bcryptjs your-password
|
|
66
|
+
> ```
|
|
67
|
+
|
|
68
|
+
### Docker Deployment
|
|
69
|
+
|
|
70
|
+
**Recommended**: Mount your custom config:
|
|
71
|
+
```bash
|
|
72
|
+
docker run -p 3000:3000 -v $(pwd)/mcp_settings.json:/app/mcp_settings.json samanhappy/mcphub
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
or run with default settings:
|
|
76
|
+
```bash
|
|
77
|
+
docker run -p 3000:3000 samanhappy/mcphub
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Access the Dashboard
|
|
81
|
+
|
|
82
|
+
Open `http://localhost:3000` and log in with your credentials.
|
|
83
|
+
> **Note**: Default credentials are `admin` / `admin123`.
|
|
84
|
+
|
|
85
|
+
**Dashboard Overview**:
|
|
86
|
+
- Live status of all MCP servers
|
|
87
|
+
- Enable/disable or reconfigure servers
|
|
88
|
+
- Group management for organizing servers
|
|
89
|
+
- User administration for access control
|
|
90
|
+
|
|
91
|
+
### Streamable HTTP Endpoint
|
|
92
|
+
> As of now, support for streaming HTTP endpoints varies across different AI clients. If you encounter issues, you can use the SSE endpoint or wait for future updates.
|
|
93
|
+
|
|
94
|
+
Connect AI clients (e.g., Claude Desktop, Cursor, DeepChat, etc.) via:
|
|
95
|
+
```
|
|
96
|
+
http://localhost:3000/mcp
|
|
97
|
+
```
|
|
98
|
+
This endpoint provides a unified streamable HTTP interface for all your MCP servers. It allows you to:
|
|
99
|
+
- Send requests to any configured MCP server
|
|
100
|
+
- Receive responses in real-time
|
|
101
|
+
- Easily integrate with various AI clients and tools
|
|
102
|
+
- Use the same endpoint for all servers, simplifying your integration process
|
|
103
|
+
|
|
104
|
+
**Group-Specific Endpoints (Recommended)**:
|
|
105
|
+
|
|
106
|
+

|
|
107
|
+
|
|
108
|
+
For targeted access to specific server groups, use the group-based HTTP endpoint:
|
|
109
|
+
```
|
|
110
|
+
http://localhost:3000/mcp/{group}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Where `{group}` is the ID or name of the group you created in the dashboard. This allows you to:
|
|
114
|
+
- Connect to a specific subset of MCP servers organized by use case
|
|
115
|
+
- Isolate different AI tools to access only relevant servers
|
|
116
|
+
- Implement more granular access control for different environments or teams
|
|
117
|
+
|
|
118
|
+
### SSE Endpoint (Deprecated in Future)
|
|
119
|
+
|
|
120
|
+
Connect AI clients (e.g., Claude Desktop, Cursor, DeepChat, etc.) via:
|
|
121
|
+
```
|
|
122
|
+
http://localhost:3000/sse
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
For targeted access to specific server groups, use the group-based SSE endpoint:
|
|
126
|
+
```
|
|
127
|
+
http://localhost:3000/sse/{group}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## 🧑💻 Local Development
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
git clone https://github.com/samanhappy/mcphub.git
|
|
134
|
+
cd mcphub
|
|
135
|
+
pnpm install
|
|
136
|
+
pnpm dev
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
This starts both frontend and backend in development mode with hot-reloading.
|
|
140
|
+
|
|
141
|
+
> For windows users, you may need to start the backend server and frontend separately: `pnpm backend:dev`, `pnpm frontend:dev`.
|
|
142
|
+
|
|
143
|
+
## 🛠️ Common Issues
|
|
144
|
+
|
|
145
|
+
### Using Nginx as a Reverse Proxy
|
|
146
|
+
If you are using Nginx to reverse proxy MCPHub, please make sure to add the following configuration in your Nginx setup:
|
|
147
|
+
|
|
148
|
+
```nginx
|
|
149
|
+
proxy_buffering off
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## 🔍 Tech Stack
|
|
153
|
+
|
|
154
|
+
- **Backend**: Node.js, Express, TypeScript
|
|
155
|
+
- **Frontend**: React, Vite, Tailwind CSS
|
|
156
|
+
- **Auth**: JWT & bcrypt
|
|
157
|
+
- **Protocol**: Model Context Protocol SDK
|
|
158
|
+
|
|
159
|
+
## 👥 Contributing
|
|
160
|
+
|
|
161
|
+
Contributions are welcome!
|
|
162
|
+
|
|
163
|
+
- New features & optimizations
|
|
164
|
+
- Documentation improvements
|
|
165
|
+
- Bug reports & fixes
|
|
166
|
+
- Translations & suggestions
|
|
167
|
+
|
|
168
|
+
## 📄 License
|
|
169
|
+
|
|
170
|
+
Licensed under the [Apache 2.0 License](LICENSE).
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# MCPHub:一站式 MCP 服务器聚合平台
|
|
2
|
+
|
|
3
|
+
[English Version](README.md) | 中文版
|
|
4
|
+
|
|
5
|
+
MCPHub 是一个统一的 MCP(Model Context Protocol,模型上下文协议)服务器聚合平台,可以根据场景将多个服务器聚合到不同的 SSE 端点。它通过直观的界面和强大的协议处理能力,简化了您的 AI 工具集成流程。
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## 🚀 功能亮点
|
|
10
|
+
|
|
11
|
+
- **开箱即用的 MCP 服务器支持**:无缝集成 `amap-maps`、`playwright`、`fetch`、`slack` 等常见服务器。
|
|
12
|
+
- **集中式管理控制台**:在一个简洁的 Web UI 中实时监控所有服务器的状态和性能指标。
|
|
13
|
+
- **灵活的协议兼容**:完全支持 stdio 和 SSE 两种 MCP 协议。
|
|
14
|
+
- **热插拔式配置**:在运行时动态添加、移除或更新服务器配置,无需停机。
|
|
15
|
+
- **基于分组的访问控制**:自定义分组并管理服务器访问权限。
|
|
16
|
+
- **安全认证机制**:内置用户管理,基于 JWT 和 bcrypt,实现角色权限控制。
|
|
17
|
+
- **Docker 就绪**:提供容器化镜像,快速部署。
|
|
18
|
+
|
|
19
|
+
## 🔧 快速开始
|
|
20
|
+
|
|
21
|
+
### 可选配置
|
|
22
|
+
|
|
23
|
+
通过创建 `mcp_settings.json` 自定义服务器设置:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"mcpServers": {
|
|
28
|
+
"amap": {
|
|
29
|
+
"command": "npx",
|
|
30
|
+
"args": ["-y", "@amap/amap-maps-mcp-server"],
|
|
31
|
+
"env": {
|
|
32
|
+
"AMAP_MAPS_API_KEY": "your-api-key"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"playwright": {
|
|
36
|
+
"command": "npx",
|
|
37
|
+
"args": ["@playwright/mcp@latest", "--headless"]
|
|
38
|
+
},
|
|
39
|
+
"fetch": {
|
|
40
|
+
"command": "uvx",
|
|
41
|
+
"args": ["mcp-server-fetch"]
|
|
42
|
+
},
|
|
43
|
+
"slack": {
|
|
44
|
+
"command": "npx",
|
|
45
|
+
"args": ["-y", "@modelcontextprotocol/server-slack"],
|
|
46
|
+
"env": {
|
|
47
|
+
"SLACK_BOT_TOKEN": "your-bot-token",
|
|
48
|
+
"SLACK_TEAM_ID": "your-team-id"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"users": [
|
|
53
|
+
{
|
|
54
|
+
"username": "admin",
|
|
55
|
+
"password": "$2b$10$Vt7krIvjNgyN67LXqly0uOcTpN0LI55cYRbcKC71pUDAP0nJ7RPa.",
|
|
56
|
+
"isAdmin": true
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
> **提示**:默认用户名/密码为 `admin` / `admin123`。密码已通过 bcrypt 安全哈希。生成新密码哈希:
|
|
63
|
+
>
|
|
64
|
+
> ```bash
|
|
65
|
+
> npx bcryptjs your-password
|
|
66
|
+
> ```
|
|
67
|
+
|
|
68
|
+
### Docker 部署
|
|
69
|
+
|
|
70
|
+
**推荐**:挂载自定义配置:
|
|
71
|
+
```bash
|
|
72
|
+
docker run -p 3000:3000 -v $(pwd)/mcp_settings.json:/app/mcp_settings.json samanhappy/mcphub
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
或使用默认配置运行:
|
|
76
|
+
```bash
|
|
77
|
+
docker run -p 3000:3000 samanhappy/mcphub
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 访问控制台
|
|
81
|
+
|
|
82
|
+
打开 `http://localhost:3000`,使用您的账号登录。
|
|
83
|
+
> **提示**:默认用户名/密码为 `admin` / `admin123`。
|
|
84
|
+
|
|
85
|
+
**控制台功能**:
|
|
86
|
+
- 实时监控所有 MCP 服务器状态
|
|
87
|
+
- 启用/禁用或重新配置服务器
|
|
88
|
+
- 分组管理,组织服务器访问
|
|
89
|
+
- 用户管理,设定权限
|
|
90
|
+
|
|
91
|
+
### 支持流式的 HTTP 端点
|
|
92
|
+
> 截至目前,各家 AI 客户端对流式的 HTTP 端点支持不一,如果遇到问题,可以使用 SSE 端点或者等待更新。
|
|
93
|
+
|
|
94
|
+
通过以下地址连接 AI 客户端(如 Claude Desktop、Cursor、DeepChat 等):
|
|
95
|
+
```
|
|
96
|
+
http://localhost:3000/mcp
|
|
97
|
+
```
|
|
98
|
+
这个端点为所有 MCP 服务器提供统一的流式 HTTP 接口。它允许您:
|
|
99
|
+
- 向任何配置的 MCP 服务器发送请求
|
|
100
|
+
- 实时接收响应
|
|
101
|
+
- 轻松与各种 AI 客户端和工具集成
|
|
102
|
+
- 对所有服务器使用相同的端点,简化集成过程
|
|
103
|
+
|
|
104
|
+
**基于分组的 HTTP 端点(推荐)**:
|
|
105
|
+

|
|
106
|
+
要针对特定服务器分组进行访问,请使用基于分组的 HTTP 端点:
|
|
107
|
+
```
|
|
108
|
+
http://localhost:3000/mcp/{group}
|
|
109
|
+
```
|
|
110
|
+
其中 `{group}` 是您在控制面板中创建的分组 ID 或名称。这样做可以:
|
|
111
|
+
- 连接到按用例组织的特定 MCP 服务器子集
|
|
112
|
+
- 隔离不同的 AI 工具,使其只能访问相关服务器
|
|
113
|
+
- 为不同环境或团队实现更精细的访问控制
|
|
114
|
+
- 通过分组名称轻松识别和管理服务器
|
|
115
|
+
- 允许不同的 AI 客户端使用相同的端点,简化集成过程
|
|
116
|
+
|
|
117
|
+
### SSE 端点集成 (即将废弃)
|
|
118
|
+
|
|
119
|
+
通过以下地址连接 AI 客户端(如 Claude Desktop、Cursor、DeepChat 等):
|
|
120
|
+
```
|
|
121
|
+
http://localhost:3000/sse
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
要针对特定服务器分组进行访问,请使用基于分组的 SSE 端点:
|
|
125
|
+
```
|
|
126
|
+
http://localhost:3000/sse/{group}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## 🧑💻 本地开发
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
git clone https://github.com/samanhappy/mcphub.git
|
|
133
|
+
cd mcphub
|
|
134
|
+
pnpm install
|
|
135
|
+
pnpm dev
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
此命令将在开发模式下启动前后端,并启用热重载。
|
|
139
|
+
|
|
140
|
+
> 针对 Windows 用户,可能需要分别启动后端服务器和前端:`pnpm backend:dev`,`pnpm frontend:dev`。
|
|
141
|
+
|
|
142
|
+
## 🛠️ 常见问题
|
|
143
|
+
|
|
144
|
+
### 使用 nginx 反向代理
|
|
145
|
+
如果您在使用 nginx 反向代理 MCPHub,请确保在 nginx 配置中添加以下内容:
|
|
146
|
+
|
|
147
|
+
```nginx
|
|
148
|
+
proxy_buffering off
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## 🔍 技术栈
|
|
152
|
+
|
|
153
|
+
- **后端**:Node.js、Express、TypeScript
|
|
154
|
+
- **前端**:React、Vite、Tailwind CSS
|
|
155
|
+
- **认证**:JWT & bcrypt
|
|
156
|
+
- **协议**:Model Context Protocol SDK
|
|
157
|
+
|
|
158
|
+
## 👥 贡献指南
|
|
159
|
+
|
|
160
|
+
期待您的贡献!
|
|
161
|
+
|
|
162
|
+
- 新功能与优化
|
|
163
|
+
- 文档完善
|
|
164
|
+
- Bug 报告与修复
|
|
165
|
+
- 翻译与建议
|
|
166
|
+
|
|
167
|
+
欢迎加入企微交流共建群,由于群人数限制,有兴趣的同学可以扫码添加管理员为好友后拉入群聊。
|
|
168
|
+
|
|
169
|
+
<img src="assets/wexin.png" width="350">
|
|
170
|
+
|
|
171
|
+
## 📄 许可证
|
|
172
|
+
|
|
173
|
+
本项目采用 [Apache 2.0 许可证](LICENSE)。
|
package/bin/mcphub.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { dirname, resolve } from 'path';
|
|
5
|
+
import { spawn } from 'child_process';
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
const rootDir = resolve(__dirname, '..');
|
|
10
|
+
|
|
11
|
+
// 检查是否有参数
|
|
12
|
+
const args = process.argv.slice(2);
|
|
13
|
+
const isDev = args.includes('--dev');
|
|
14
|
+
|
|
15
|
+
async function main() {
|
|
16
|
+
try {
|
|
17
|
+
console.log('Starting MCPHub...');
|
|
18
|
+
|
|
19
|
+
if (isDev) {
|
|
20
|
+
// 开发模式:同时启动前端和后端
|
|
21
|
+
console.log('Running in development mode');
|
|
22
|
+
const child = spawn('pnpm', ['dev'], {
|
|
23
|
+
cwd: rootDir,
|
|
24
|
+
stdio: 'inherit',
|
|
25
|
+
shell: true
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// 处理进程退出
|
|
29
|
+
process.on('SIGINT', () => {
|
|
30
|
+
child.kill('SIGINT');
|
|
31
|
+
process.exit(0);
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
34
|
+
// 生产模式:只启动后端(假设前端已经构建)
|
|
35
|
+
console.log('Running in production mode');
|
|
36
|
+
const child = spawn('node', ['dist/index.js'], {
|
|
37
|
+
cwd: rootDir,
|
|
38
|
+
stdio: 'inherit',
|
|
39
|
+
shell: true
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// 处理进程退出
|
|
43
|
+
process.on('SIGINT', () => {
|
|
44
|
+
child.kill('SIGINT');
|
|
45
|
+
process.exit(0);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error('Failed to start MCPHub:', error);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
main();
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
dotenv.config();
|
|
5
|
+
const defaultConfig = {
|
|
6
|
+
port: process.env.PORT || 3000,
|
|
7
|
+
initTimeout: process.env.INIT_TIMEOUT || 300000,
|
|
8
|
+
timeout: process.env.REQUEST_TIMEOUT || 60000,
|
|
9
|
+
mcpHubName: 'mcphub',
|
|
10
|
+
mcpHubVersion: '0.0.1',
|
|
11
|
+
};
|
|
12
|
+
export const getSettingsPath = () => {
|
|
13
|
+
return path.resolve(process.cwd(), 'mcp_settings.json');
|
|
14
|
+
};
|
|
15
|
+
export const loadSettings = () => {
|
|
16
|
+
const settingsPath = getSettingsPath();
|
|
17
|
+
try {
|
|
18
|
+
const settingsData = fs.readFileSync(settingsPath, 'utf8');
|
|
19
|
+
return JSON.parse(settingsData);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
console.error(`Failed to load settings from ${settingsPath}:`, error);
|
|
23
|
+
return { mcpServers: {}, users: [] };
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
export const saveSettings = (settings) => {
|
|
27
|
+
const settingsPath = getSettingsPath();
|
|
28
|
+
try {
|
|
29
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8');
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error(`Failed to save settings to ${settingsPath}:`, error);
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
export const expandEnvVars = (value) => {
|
|
38
|
+
return value.replace(/\$\{([^}]+)\}/g, (_, key) => process.env[key] || '');
|
|
39
|
+
};
|
|
40
|
+
export default defaultConfig;
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAGpB,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,MAAM,aAAa,GAAG;IACpB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI;IAC9B,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,MAAM;IAC/C,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,KAAK;IAC7C,UAAU,EAAE,QAAQ;IACpB,aAAa,EAAE,OAAO;CACvB,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,GAAW,EAAE;IAC1C,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAC;AAC1D,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,GAAgB,EAAE;IAC5C,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,gCAAgC,YAAY,GAAG,EAAE,KAAK,CAAC,CAAC;QACtE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACvC,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,QAAqB,EAAW,EAAE;IAC7D,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IACvC,IAAI,CAAC;QACH,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAC1E,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,YAAY,GAAG,EAAE,KAAK,CAAC,CAAC;QACpE,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAa,EAAU,EAAE;IACrD,OAAO,KAAK,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;AAC7E,CAAC,CAAC;AAEF,eAAe,aAAa,CAAC"}
|