Compare commits

..

222 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
1a35c07cd7 Add comprehensive security fix documentation
- Document vulnerability details and attack scenarios
- Explain root causes with code examples
- Detail all fixes implemented
- Provide before/after verification examples
- Include security recommendations
- Reference all security tests

Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-11-23 06:35:14 +00:00
copilot-swe-agent[bot]
262778353f Add comprehensive security tests for authentication bypass fixes
- Add tests validating user-scoped route authentication
- Add tests preventing user impersonation attacks
- Add tests for bearer auth configuration bypass fix
- Document vulnerability details and fixes in test comments
- All 10 security tests pass successfully

Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-11-23 06:34:06 +00:00
copilot-swe-agent[bot]
500eec3979 Fix authentication bypass vulnerabilities in MCP/SSE endpoints
- Fix validateBearerAuth to use loadOriginalSettings() instead of loadSettings()
  to prevent bearer auth bypass when no user context exists
- Add authentication validation to sseUserContextMiddleware for user-scoped routes
  to prevent user impersonation via URL path parameters
- Require valid OAuth/bearer token for accessing /:user/mcp and /:user/sse endpoints
- Return 401 Unauthorized for user-scoped routes without authentication
- Return 403 Forbidden when authenticated user doesn't match requested username

Security improvements:
1. Bearer auth now correctly reads enableBearerAuth from system config
2. User-scoped endpoints now require authentication
3. Users can only access their own resources
4. Prevents impersonation attacks via URL manipulation

Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-11-23 06:30:52 +00:00
copilot-swe-agent[bot]
5a10d5934d Initial plan 2025-11-23 06:07:49 +00:00
samanhappy
6de3221974 feat: Enhance user forms and user management UI (#437) 2025-11-23 13:50:55 +08:00
samanhappy
ac0b60ed4b feat: Implement keepalive functionality for SSE and StreamableHTTP connections (#442) 2025-11-22 12:07:21 +08:00
samanhappy
a57218d076 fix: Remove test routing and oauthClients configurations from settings (#441) 2025-11-22 11:27:00 +08:00
samanhappy
8c985b7de1 fix: Include mcpServers, oauthClients, and oauthTokens in merged settings for non-admin users (#440) 2025-11-21 17:16:48 +08:00
samanhappy
01bb011736 fix: Use base URL from settings for dynamic client registration and metadata endpoints (#438) 2025-11-21 16:20:54 +08:00
Copilot
449e6ea4fd Add OAuth 2.0 authorization server to enable ChatGPT Web integration (#413)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
Co-authored-by: samanhappy <samanhappy@gmail.com>
2025-11-21 13:25:02 +08:00
cheestard
1869f283ba fix: Bad Request: No valid session ID provided (#405) (#427) 2025-11-19 18:17:37 +08:00
Copilot
07adeab036 feat: Add copy button for tool names in server tool list (#435)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-11-19 11:41:11 +08:00
dependabot[bot]
5d7d8fdd1a chore(deps): bump js-yaml from 3.14.1 to 3.14.2 (#436)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-19 11:38:24 +08:00
Copilot
fb847797c0 Add missing API documentation for tool execution and management endpoints (#430)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-11-12 22:18:56 +08:00
Alptekin Gülcan
8df2b4704a Fix: Handle ToolName in CallToolRequest to Resolve Server Discovery Issues (#429)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-12 09:13:50 +08:00
samanhappy
602b5cb80e fix: update GitHub repository links to point to the new repository (#423) 2025-11-03 17:04:49 +08:00
samanhappy
e63f045819 refactor: remove outdated references to MCP protocol and cloud deployment in documentation (#422) 2025-11-03 17:02:10 +08:00
Chengwei Guo
a4e4791b60 fix the deployment on kubernetes (#417) 2025-11-03 14:16:12 +08:00
samanhappy
01370ea959 Revert "Feat: Enhance package cache for stdio servers (#400)" (#418) 2025-11-03 13:35:24 +08:00
samanhappy
f5d66c1bb7 fix versions for react and react-dom (#414) 2025-11-02 23:02:25 +08:00
dependabot[bot]
9e59dd9fb0 chore(deps-dev): bump react and @types/react (#407)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-02 22:48:13 +08:00
dependabot[bot]
250487f042 chore(deps-dev): bump lucide-react from 0.486.0 to 0.552.0 (#408)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-02 22:45:01 +08:00
dependabot[bot]
da91708420 chore(deps): bump i18next from 25.5.0 to 25.6.0 (#409)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-02 22:44:42 +08:00
dependabot[bot]
576bba1f9e chore(deps): bump openai from 4.104.0 to 6.7.0 (#410)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-02 22:44:21 +08:00
dependabot[bot]
f4b83929a6 chore(deps): bump axios from 1.12.2 to 1.13.1 (#406)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-02 22:43:57 +08:00
Alptekin Gülcan
3825f389cd Feat: Add Turkish localization (tr) (#411) 2025-11-02 22:43:18 +08:00
samanhappy
44e0309fd4 Feat: Enhance package cache for stdio servers (#400) 2025-10-31 21:56:43 +08:00
Copilot
7e570a900a Fix: Convert form parameters to schema-defined types before MCP tool calls (#397)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-10-29 18:41:23 +08:00
Copilot
6268a02c0e Fix URL routing for MCP servers with slashes in names (#396)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-10-29 18:37:24 +08:00
samanhappy
695d663939 Fix display for null server author (#398) 2025-10-29 14:44:09 +08:00
samanhappy
d595e5d874 Fix support for nested smart group segments in MCP routing (#394) 2025-10-28 17:51:58 +08:00
Copilot
ff797b4ab9 Add group-scoped smart routing via $smart/{group} pattern (#388)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-10-26 20:51:55 +08:00
samanhappy
9105507722 Refactor: Clean up code formatting and improve readability across multiple files (#387) 2025-10-26 19:27:30 +08:00
Copilot
f79028ed64 Expand environment variables throughout mcp_settings.json configuration (#384)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-10-26 19:25:53 +08:00
Copilot
5ca5e2ad47 Add password security: default credential warning and strength validation (#386)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-10-26 19:22:51 +08:00
Copilot
2f7726b008 Add JSON import for MCP servers (#385)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
Co-authored-by: samanhappy <samanhappy@gmail.com>
2025-10-26 19:13:06 +08:00
Copilot
26b26a5fb1 Add OAuth support for upstream MCP servers (#381)
Co-authored-by: samanhappy <samanhappy@gmail.com>
2025-10-26 16:09:34 +08:00
Copilot
7dbd6c386e Fix: Environment variable expansion in headers for HTTP-based MCP transports (#380)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-10-23 19:18:50 +08:00
Copilot
c1fee91142 Fix Dependabot alert #18: Remove outdated package-lock.json causing axios vulnerability false positive (#379)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-10-22 15:16:24 +08:00
samanhappy
1130f6833e fix: use reconnect mechanism for sse tool calling error (#378) 2025-10-22 12:05:21 +08:00
dependabot[bot]
c3f1de8f5b chore(deps-dev): bump vite from 6.3.6 to 6.4.1 (#376)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-22 12:04:16 +08:00
samanhappy
86367a4875 feat: integrate offcial mcp server registry (#374) 2025-10-19 21:15:25 +08:00
samanhappy
bd4c546bba fix settings data export & parsing error (#373) 2025-10-16 13:08:28 +08:00
Copilot
3e9e5cc3c9 feat: Auto-start Docker daemon when installed in container (#370)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
Co-authored-by: samanhappy <samanhappy@gmail.com>
2025-10-13 22:38:13 +08:00
samanhappy
16a92096b3 feat: Enhance package root detection and version retrieval using ESM-compatible methods (#371) 2025-10-13 22:36:29 +08:00
Copilot
4d736c543d feat: Add MCP settings export and copy functionality (#367)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
Co-authored-by: samanhappy <samanhappy@gmail.com>
2025-10-13 19:39:01 +08:00
samanhappy
f53c4a0e3b fix: assign server name from key in getMarketServers function (#369) 2025-10-13 18:19:21 +08:00
Copilot
d4bdb099d0 Add Docker CLI support to Docker image with INSTALL_EXT build argument (#366)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-10-12 16:51:02 +08:00
samanhappy
435227cbd4 fix: improve error handling and directory creation for settings path (#364) 2025-10-12 15:30:40 +08:00
Copilot
6a59becd8d Fix Windows startup error: Convert paths to file:// URLs for ESM dynamic imports (#363)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
Co-authored-by: samanhappy <samanhappy@gmail.com>
2025-10-12 11:31:44 +08:00
samanhappy
91698a50e3 fix: use specified environment setting path when available (#359) 2025-10-11 23:44:23 +08:00
samanhappy
a5d5045832 fix: add groups handling in mergeSettings method (#362) 2025-10-11 23:29:59 +08:00
samanhappy
198ea85225 feat: implement user management features with add, edit, and delete functionality 2025-10-02 15:11:08 +08:00
dependabot[bot]
6b39916909 chore(deps): bump typeorm from 0.3.26 to 0.3.27 (#356)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-02 14:47:55 +08:00
dependabot[bot]
9e8db370ff chore(deps-dev): bump @tailwindcss/postcss from 4.1.12 to 4.1.13 (#358)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-02 14:47:09 +08:00
dependabot[bot]
5d8bc44a73 chore(deps-dev): bump @types/node from 22.17.2 to 24.6.1 (#357)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-02 14:44:13 +08:00
dependabot[bot]
021901dbda chore(deps-dev): bump jest and @types/jest (#354)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-02 14:40:42 +08:00
WuWen
f6934a32dc feat: add configurable name separator for tools and prompts (#353) 2025-10-02 14:40:01 +08:00
samanhappy
7685b9bca8 feat: enhance visual hierarchy on LoginPage by increasing slogan size and spacing (#347) 2025-09-20 17:23:54 +08:00
samanhappy
c2dd91606f chore(deps): update @modelcontextprotocol/sdk to 1.18.1 and axios to 1.12.2 (#346) 2025-09-20 17:16:04 +08:00
samanhappy
66b6053f7f feat: add passthrough headers support for OpenAPI client and MCP protocol (#345) 2025-09-20 17:12:20 +08:00
dependabot[bot]
ba50a78879 chore(deps): bump axios from 1.11.0 to 1.12.0 (#342)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-14 16:14:13 +08:00
comeback01
a856404963 docs: add French translation for README (#339)
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2025-09-12 17:56:00 +08:00
comeback01
9a65532a50 feat: add french localization (#337)
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2025-09-12 14:27:05 +08:00
dependabot[bot]
c5aa97de50 chore(deps-dev): bump vite from 6.3.5 to 6.3.6 (#334)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-10 12:42:00 +08:00
dependabot[bot]
271c9fe2c3 chore(deps-dev): bump i18next from 24.2.3 to 25.4.2 (#329)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-05 08:51:54 +08:00
dependabot[bot]
d59961c4d4 chore(deps-dev): bump next from 15.5.0 to 15.5.2 (#328)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-05 08:51:23 +08:00
dependabot[bot]
d0ec80303a chore(deps-dev): bump jest-mock-extended from 4.0.0-beta1 to 4.0.0 (#330)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-04 22:49:30 +08:00
dependabot[bot]
69e92b5aa8 chore(deps): bump @apidevtools/swagger-parser from 11.0.1 to 12.0.0 (#331)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-04 22:48:29 +08:00
dependabot[bot]
5acae64b29 chore(deps-dev): bump @typescript-eslint/eslint-plugin from 6.21.0 to 7.0.0 (#327)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-04 22:47:30 +08:00
samanhappy
a5fc4a429d fix: ensure settings cache is cleared after saving and clearing cache (#326) 2025-09-01 10:15:50 +08:00
Junsen Huang
ce15330016 fix(server-context): fix server edite error (#325) 2025-08-30 17:37:30 +08:00
samanhappy
621bc36560 feat: Add OpenAPI-compatible tool execution endpoints for named APIs (#316) 2025-08-30 16:00:15 +08:00
Junsen Huang
c398223824 feat: refactor server data management to use global context (#319) 2025-08-28 22:15:16 +08:00
Copilot
5dd3e7978e Generate comprehensive GitHub Copilot instructions for MCPHub development (#314)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-08-27 21:58:06 +08:00
samanhappy
f577351f04 fix: set current working directory for StdioClientTransport to homedir (#311) 2025-08-27 19:23:00 +08:00
Copilot
62de87b1a4 Add granular OpenAPI endpoints for server-level and group-level tool access (#309)
Co-authored-by: samanhappy <samanhappy@gmail.com>
2025-08-27 17:25:32 +08:00
samanhappy
bbd6c891c9 feat(dao): Implement comprehensive DAO layer (#308)
Co-authored-by: samanhappy@qq.com <my6051199>
2025-08-27 15:21:30 +08:00
Copilot
f9019545c3 Fix integer parameter conversion in OpenAPI endpoints (#306)
Co-authored-by: samanhappy <samanhappy@gmail.com>
2025-08-27 11:04:25 +08:00
samanhappy
d778536388 fix: update tool call API endpoint structure and enhance error handling (#300) 2025-08-26 18:49:34 +08:00
Copilot
976e90679d Add OpenAPI specification generation for OpenWebUI integration (#295)
Co-authored-by: samanhappy <samanhappy@gmail.com>
2025-08-26 14:54:19 +08:00
samanhappy
f6ee9beed3 refactor: remove MCPRouter referer and title input sections from SettingsPage (#294) 2025-08-25 15:51:02 +08:00
samanhappy
69a800fa7a fix: update MCPRouter referer URL to new domain (#293) 2025-08-25 13:25:37 +08:00
Copilot
83cbd16821 Fix Dependabot security alert #11 - resolve sha.js and brace-expansion vulnerabilities (#292)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-08-25 12:26:04 +08:00
samanhappy
9300814994 Add .git to .dockerignore to prevent Git files from being included in Docker builds (#290) 2025-08-24 15:37:38 +08:00
Rilomilo
9952927a13 remove redundant code (#288) 2025-08-24 11:40:33 +08:00
samanhappy
4547ae526a fix: adjust spacing and heading size in LoginPage for improved layout (#286)
Co-authored-by: samanhappy@qq.com <my6051199>
2025-08-20 22:14:41 +08:00
Copilot
80b83bb029 Fix missing i18n translation for api.errors.invalid_credentials (#285)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
2025-08-20 21:06:03 +08:00
Copilot
fa2de88fea Center login form and simplify layout with main slogan only (#283)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: samanhappy <2755122+samanhappy@users.noreply.github.com>
Co-authored-by: samanhappy <samanhappy@gmail.com>
2025-08-20 14:37:10 +08:00
samanhappy
6020611f57 Add prompt management functionality to MCP server (#281) 2025-08-20 14:23:55 +08:00
samanhappy
81c3091a5c fix: filter out empty values in tool arguments for improved functionality (#280)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-20 14:21:51 +08:00
samanhappy
6a8f246dff fix: adjust layout for LoginPage to improve responsiveness and styling (#278) 2025-08-14 16:28:47 +08:00
samanhappy
2bef1fb0bd fix: update @modelcontextprotocol/sdk dependency to version 1.17.2 (#277) 2025-08-14 15:17:19 +08:00
samanhappy
bdb5b37cf5 Add API documentation (#275) 2025-08-14 14:12:15 +08:00
samanhappy
cbb3b15ba2 fix: standardize naming to MCPHub across documentation and UI (#271)
Co-authored-by: samanhappy@qq.com <my6051199>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-13 21:54:41 +08:00
samanhappy
77b423fbcc Refactor JWT secret management and enhance documentation (#270) 2025-08-11 19:09:33 +08:00
samanhappy
604fe4f71d fix: remove registration endpoint from authentication bypass in middleware (#267) 2025-08-11 14:18:28 +08:00
samanhappy
907bca8aac Refactor cloud and market pages for improved functionality and UI consistency (#265) 2025-08-10 17:39:34 +08:00
samanhappy
8c58200dcc feat: add health check endpoint to monitor MCP server status (#264) 2025-08-10 16:46:22 +08:00
samanhappy
0b4dc453a5 fix: reinitialize mcp server connection on update (#263) 2025-08-10 16:20:36 +08:00
samanhappy
35012f99fc refine docs 2025-08-10 12:52:54 +08:00
samanhappy
22ad4f83f6 fix: handle undefined and null values for number inputs in DynamicForm (#261)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-10 12:52:20 +08:00
samanhappy
26720d9e49 feat: introduce cloud server market (#260) 2025-08-09 21:14:26 +08:00
samanhappy
a9aa4a9a08 feat: Update registerService to handle environment-specific service overrides (#257) 2025-08-05 14:48:48 +08:00
samanhappy
48bcf9f5f0 feat: Add cleanInputSchema function to remove $schema field from inputSchema (#255) 2025-08-05 13:45:52 +08:00
samanhappy
f63f06d879 feat: Enhance authentication flow by integrating permissions retrieval and updating related services (#256) 2025-08-05 13:45:31 +08:00
samanhappy
63b356b8d7 Add Chinese localization support and i18n middleware (#253) 2025-08-03 11:53:04 +08:00
samanhappy
a6cea2ad3f feat: Enhance group management with server tool configuration (#250) 2025-07-29 17:31:05 +08:00
samanhappy
5bb2715094 refactor: simplify LanguageSwitch component by removing unnecessary language count checks and enhancing dropdown behavior (#249) 2025-07-27 20:44:50 +08:00
samanhappy
9b40f7e101 feat: enhance LanguageSwitch component with language toggle functionality and improve dropdown behavior; update UserProfileMenu styles (#248) 2025-07-26 22:58:01 +08:00
samanhappy
df872823c1 Implement language and theme switchers in Header (#247) 2025-07-26 21:46:14 +08:00
samanhappy
9304653c34 feat: enhance GroupCard with copy options for ID, URL, and JSON; update translations (#246)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-25 14:30:52 +08:00
dependabot[bot]
b5685b7010 chore(deps): bump axios from 1.10.0 to 1.11.0 (#245)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-24 10:39:17 +08:00
samanhappy
89c37b2f02 Enhance operation name generation in OpenAPIClient (#244) 2025-07-23 19:02:43 +08:00
Oven
c316cb896e fix: create when dxt upload path does not exist (#243) 2025-07-23 13:47:11 +08:00
samanhappy
bc3c8facfa feat: add replaceEnvVarsInArray function and integrate it into server transport configuration (#241)
Co-authored-by: samanhappy@qq.com <my6051199>
2025-07-22 23:24:04 +08:00
dependabot[bot]
69afb865c0 chore(deps): bump brace-expansion from 1.1.11 to 1.1.12 (#231)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 23:07:20 +08:00
dependabot[bot]
ba30d88840 chore(deps): bump multer from 2.0.1 to 2.0.2 (#229)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 23:06:24 +08:00
samanhappy
6d0d622bd8 feat: add permissions for contents and packages in build workflow (#238) 2025-07-22 10:05:16 +08:00
samanhappy
ab50c7e9eb feat: add conditional check for repository in build and npm publish workflows (#236)
Co-authored-by: samanhappy@qq.com <my6051199>
2025-07-22 08:56:50 +08:00
samanhappy
e507bea2e3 Refactor service registration and revert lazy loading implementation (#234) 2025-07-20 22:30:09 +08:00
samanhappy
0f00ad7200 feat: implement lazy loading for data service and enhance service registration (#233) 2025-07-20 21:37:43 +08:00
samanhappy
b0b0c93337 feat: enable immediate loading of service overrides during registration (#232) 2025-07-20 20:35:00 +08:00
samanhappy
20fd355b87 feat: enhance JSON serialization safety & add dxt upload limit (#230) 2025-07-20 19:18:10 +08:00
dependabot[bot]
4388084704 chore(deps): bump typeorm from 0.3.24 to 0.3.25 (#210)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-07 09:54:52 +08:00
dependabot[bot]
fe2535461d chore(deps-dev): bump @types/react-dom from 19.1.5 to 19.1.6 (#211)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-07 09:39:52 +08:00
dependabot[bot]
985598e529 chore(deps): bump pg from 8.16.0 to 8.16.3 (#212)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-05 15:24:37 +08:00
dependabot[bot]
b2b6d0588b chore(deps-dev): bump tailwindcss from 4.1.8 to 4.1.11 (#213)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 14:11:24 +08:00
dependabot[bot]
64628ee3ed chore(deps-dev): bump tsx from 4.19.4 to 4.20.3 (#214)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-02 18:04:25 +08:00
samanhappy
66d4142039 feat: add variable detection and confirmation dialogs in server forms (#205) 2025-06-29 22:23:42 +08:00
samanhappy
cf72295f99 Refactor UI components across multiple pages for improved styling and consistency (#204) 2025-06-29 22:01:00 +08:00
samanhappy
89f85c73ff fix: resolve race conditions in initializeClientsFromSettings (#201) 2025-06-28 22:11:14 +08:00
samanhappy
adabf1d92b feat:support DXT file server installation (#200) 2025-06-27 14:45:24 +08:00
samanhappy
c3a6dfadb4 feat: Add dynamic header input fields for server configuration in ServerForm (#193) 2025-06-20 14:52:22 +08:00
samanhappy
d119be0f82 feat: Implement bearer token validation in auth middleware (#186) 2025-06-19 12:11:35 +08:00
samanhappy
1e308ec4c5 feat: add Jest testing framework and CI/CD configuration (#187)
Co-authored-by: samanhappy@qq.com <my6051199>
2025-06-18 14:02:52 +08:00
samanhappy
1bd4fd6d9c feat: Add OpenAPI support with comprehensive configuration options and client integration (#184)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-16 17:50:51 +08:00
Imgodmaoyouknow
4b3bb26301 fix: 修复从市场安装服务器时,选择SSE和Streamable HTTP不生效的问题 (#180) 2025-06-13 22:50:36 +08:00
samanhappy
40af398f68 chore: update @modelcontextprotocol/sdk to version 1.12.1 (#176) 2025-06-10 16:50:28 +08:00
samanhappy
4726f00a22 feat: add request options configuration to server form (#171) 2025-06-10 13:51:01 +08:00
samanhappy
77f64b7b98 feat: enhance DynamicForm to support array and object (#173)
Co-authored-by: samanhappy@qq.com <my6051199>
2025-06-10 13:50:14 +08:00
samanhappy
d9cbc5381a feat: implement keep-alive functionality for SSE connections (#166)
Co-authored-by: samanhappy@qq.com <my6051199>
2025-06-07 20:41:51 +08:00
samanhappy
56c6447469 feat: implement settings cache with load, save, clear, and status functions (#167) 2025-06-07 20:36:52 +08:00
samanhappy
f8149c4b0b fix: update SSE transport path to use basePath from config (#165)
Co-authored-by: samanhappy@qq.com <my6051199>
2025-06-07 20:35:20 +08:00
purefkh
e259f30539 fix: save user config when install mcp server from market (#168) 2025-06-07 20:34:51 +08:00
samanhappy
3a421bc476 fix: update tool name formatting from '/' to '-' in ToolCard and mcpService (#164)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-05 15:34:49 +08:00
samanhappy
503b60edb7 feat: add tool management features including toggle and description updates (#163)
Co-authored-by: samanhappy@qq.com <my6051199>
2025-06-04 16:03:45 +08:00
dependabot[bot]
4039a85ee1 chore(deps-dev): bump concurrently from 8.2.2 to 9.1.2 (#156)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-02 19:49:58 +08:00
dependabot[bot]
3a83b83a9e chore(deps-dev): bump @vitejs/plugin-react from 4.4.1 to 4.5.0 (#160)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-02 19:47:04 +08:00
samanhappy
c1621805de fix: expand environment variables in database and OpenAI configuration (#162) 2025-06-02 19:46:39 +08:00
samanhappy
ecf79eaef3 fix: update error response status for missing transport in SSE service (#161) 2025-06-02 10:56:23 +08:00
samanhappy
e2cb5fa467 fix: update favicon path from "/favicon.svg" to "/favicon.ico" in documentation (#155) 2025-06-01 08:27:05 +08:00
samanhappy
7193ca4cdc fix: update "Get Started" button link to point to the correct documentation URL (#154) 2025-06-01 00:23:18 +08:00
samanhappy
9675cd8533 generate documents using mintlify (#153) 2025-06-01 00:17:09 +08:00
samanhappy
65c95aaa0b feat: Implement tool management features including tool execution and result handling (#152) 2025-05-31 22:00:05 +08:00
samanhappy
d2bbadea83 Add HTTP headers support and batch update for routing configuration (#151) 2025-05-31 18:36:41 +08:00
samanhappy
394945bbc5 fix: enhance environment variable handling in replaceEnvVars and expandEnvVars functions (#149)
Co-authored-by: samanhappy@qq.com <my6051199>
2025-05-31 08:41:20 +08:00
samanhappy
bfc184afc6 fix: enhance database initialization by adding required PostgreSQL extensions and improving error handling (#144)
Co-authored-by: samanhappy@qq.com <my6051199>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-30 23:03:42 +08:00
Oven
1acacfab88 配置MCP Server时,env中填写的${xxx}值可以从环境变量中读取 (#135) 2025-05-30 23:02:34 +08:00
terrydash
63c55875b5 add env var for setting file (#147)
Co-authored-by: Xu, Guoxu | Terry | CNTD <guoxu.xu@rakuten.com>
2025-05-30 23:01:52 +08:00
samanhappy
80c6aae116 Add comprehensive documentation for MCPHub including deployment, configuration, and smart routing features (#142) 2025-05-29 15:44:39 +08:00
samanhappy
e2c5cc8ed1 fix: refine sessionId handling in handleMcpPostRequest for initialization requests (#138)
Co-authored-by: samanhappy@qq.com <my6051199>
2025-05-28 23:25:21 +08:00
samanhappy
b0a65cc6d0 fix: streamline sessionId handling in handleMcpPostRequest (#137)
Co-authored-by: samanhappy@qq.com <my6051199>
2025-05-28 22:15:14 +08:00
samanhappy
e019c9e8b3 fix: simplify server status labels in English and Chinese locales (#128) 2025-05-28 18:20:43 +08:00
samanhappy
39b69bf550 fix: improve sessionId validation and error handling in handleSseMessage (#134) 2025-05-28 14:30:35 +08:00
samanhappy
a1047321d1 feat: introduce runtime path (#132) 2025-05-27 18:34:23 +08:00
samanhappy
268ce5cce6 feat: Refactor API URL handling and add base path support (#131) 2025-05-27 16:11:35 +08:00
samanhappy
37bb3414c8 feat: add VITE_BASE_PATH environment variable and update routing in App component (#130) 2025-05-27 13:08:41 +08:00
samanhappy
c3e1fa1eee Update asset paths to use relative URLs (#129) 2025-05-27 11:55:50 +08:00
samanhappy
edfbdb7123 fix: update README and README.zh.md for clarity and consistency (#124) 2025-05-25 21:32:46 +08:00
samanhappy
9e5c2b5525 feat: introduce auto routing (#122) 2025-05-25 21:09:47 +08:00
samanhappy
27b7e766af fix: downgrade express and @types/express to compatible versions (#119) 2025-05-22 15:14:05 +08:00
dependabot[bot]
9c55f63bb1 chore(deps-dev): bump @types/node from 20.17.28 to 22.15.21 (#114)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 14:57:56 +08:00
dependabot[bot]
b1674cc630 chore(deps): bump express and @types/express (#113)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 14:56:06 +08:00
dependabot[bot]
3570232ccc chore(deps-dev): bump tailwind-merge from 3.1.0 to 3.3.0 (#112)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 14:54:29 +08:00
dependabot[bot]
f50bb08816 chore(deps-dev): bump @tailwindcss/postcss from 4.1.3 to 4.1.7 (#115)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 14:54:03 +08:00
dependabot[bot]
721674e7eb chore(deps-dev): bump @radix-ui/react-slot from 1.1.2 to 1.2.3 (#116)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 14:53:50 +08:00
samanhappy
1337eeed84 Update dependabot.yml (#111) 2025-05-21 09:39:56 +08:00
samanhappy
b14be9955b Create dependabot.yml (#110) 2025-05-21 09:37:39 +08:00
samanhappy
da45d49a5e feat: Bump Vite to v6 and update esbuild (#109)
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2025-05-21 09:34:24 +08:00
samanhappy
f46e2c22fc feat: implement dynamic package versioning and refactor MCP server initialization (#104) 2025-05-18 20:07:01 +08:00
samanhappy
ae3fe1c6f1 add mintlify doc (#106) 2025-05-17 22:42:46 +08:00
samanhappy
76a27a454e docs: add Star History section to README files (#105) 2025-05-17 20:34:02 +08:00
samanhappy
b15b71f407 fix: enhance stdio log (#103) 2025-05-17 19:40:34 +08:00
samanhappy
298d96d593 feat: enhance MCP server retrieval and logging for transport closure (#101) 2025-05-16 16:47:21 +08:00
samanhappy
d44886b81b docs: update README to enhance clarity and add new features overview (#102) 2025-05-16 13:28:46 +08:00
Lawrence Sinclair
bbe44fc540 Add MseeP.ai badge (#95) 2025-05-14 17:14:48 +08:00
samanhappy
c60b98e3d6 feat: add icons and link to Header (#94) 2025-05-14 13:54:29 +08:00
samanhappy
a447fe5b41 feat: display current version in Header and remove version display from UserProfileMenu (#93) 2025-05-14 10:19:43 +08:00
samanhappy
94d51fa03a refactor: update issue templates for consistency and clarity (#91) 2025-05-13 22:01:23 +08:00
samanhappy
b88a7240c6 Update issue templates (#90) 2025-05-13 19:57:00 +08:00
samanhappy
3c875590ce refactor: remove Node.js setup and version update steps from release workflow (#84) 2025-05-13 14:37:09 +08:00
samanhappy
26fa61fcfc feat: implement version checking and update notifications in AboutDialog and UserProfileMenu (#83) 2025-05-13 14:18:49 +08:00
samanhappy
d689541fc4 refactor: remove dependency on wait-for-npm job in build workflow (#82) 2025-05-13 13:07:21 +08:00
samanhappy
30895c4b9a refactor: remove wait-for-npm job from build workflow (#81) 2025-05-13 13:05:26 +08:00
samanhappy
37c3fd9e06 feat: add bearer authentication support for MCP requests (#79) 2025-05-13 13:02:41 +08:00
samanhappy
59454ca250 feat: add wait-for-npm job and update version from tag in build workflow (#80) 2025-05-13 13:01:54 +08:00
samanhappy
63efa0038c feat: add npmRegistry support to installation configuration (#77)
Co-authored-by: samanhappy@qq.com <my6051199>
2025-05-13 09:21:07 +08:00
samanhappy
040782da8d feat: support streamable http upstream server (#75)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-12 22:12:48 +08:00
samanhappy
f1a5f692cc feat: create MCP server for different session (#74) 2025-05-12 15:11:37 +08:00
samanhappy
5d798cfe6a feat: enhance release workflow to automatically update package.json version (#70) 2025-05-11 14:43:48 +08:00
samanhappy
0490d98c9e feat: add sponsorship section to README.md (#72) 2025-05-11 14:41:00 +08:00
samanhappy
7af3c8a2ba feat: add installation configuration support with pythonIndexUrl in settings (#67) 2025-05-10 21:33:35 +08:00
samanhappy
7c43ca359e feat: add acknowledgment section to README.zh.md (#68)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-10 21:33:22 +08:00
samanhappy
2bb6302cbc feat: enhance user experience with version info (#69)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-10 21:33:05 +08:00
samanhappy
3a3f6c984c Create FUNDING.yml (#65) 2025-05-10 11:05:07 +08:00
samanhappy
e8bc053788 fix: update react-router-dom to version 7.6.0 in package.json and pnpm-lock.yaml (#63) 2025-05-09 22:06:51 +08:00
samanhappy
bb674236c7 feat: update Node.js and pnpm versions in CI workflow; add packageManager field in package.json (#62) 2025-05-09 21:34:25 +08:00
samanhappy
0f5dfbe419 feat: support server-specified endpoint (#58) 2025-05-09 21:25:44 +08:00
samanhappy
74d1ca6a87 fix: remove unnecessary dependency from fetchMarketServers to improve performance (#56) 2025-05-09 21:24:27 +08:00
dependabot[bot]
eab421c753 chore(deps-dev): bump vite from 5.4.18 to 5.4.19 (#51)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-05 20:58:54 +08:00
samanhappy
886ca44681 Implement code changes to enhance functionality and improve performance (#52) 2025-05-05 20:54:11 +08:00
samanhappy
3d4baeef1a feat: update dependencies in pnpm-lock.yaml for improved functionality and security (#50) 2025-05-05 19:44:25 +08:00
samanhappy
4379513a35 feat: add GitHub Actions workflow for publishing to NPM (#49) 2025-05-05 19:39:09 +08:00
samanhappy
9a06bae225 fix: improve error handling in CallToolRequest by providing detailed error messages (#48) 2025-05-05 19:09:02 +08:00
samanhappy
e5aaae466f feat: add log management features including log viewing, filtering, and streaming (#45) 2025-05-02 21:41:16 +08:00
samanhappy
9b1338a356 feat: add support for HTTP_PROXY and HTTPS_PROXY environment variables in Dockerfile and entrypoint script (#42) 2025-05-02 12:40:44 +08:00
samanhappy
10d4616601 Implement theme switching and enhance dark mode support (#43) 2025-05-02 12:40:11 +08:00
samanhappy
9ca242a0e4 docs: update README and README.zh to clarify Streamable HTTP endpoint support (#41) 2025-05-01 17:42:46 +08:00
samanhappy
0a6259decf feat: enhance configuration file handling and dynamic frontend path resolution (#40)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-04-30 22:38:21 +08:00
samanhappy
7887a3a5f9 docs: update README to reflect changes in HTTP endpoint support and deprecate SSE endpoint (#38) 2025-04-28 14:49:40 +08:00
samanhappy
7f33615161 feat: support Streamable HTTP transport for downstream (#32) 2025-04-27 13:55:25 +08:00
373 changed files with 69326 additions and 5194 deletions

16
.coveragerc Normal file
View File

@@ -0,0 +1,16 @@
# Test coverage configuration
# This file tells Jest what to include/exclude from coverage reports
# Coverage patterns
- "src/**/*.{ts,tsx}"
# Exclusions
- "!src/**/*.d.ts"
- "!src/index.ts"
- "!src/**/__tests__/**"
- "!src/**/*.test.{ts,tsx}"
- "!src/**/*.spec.{ts,tsx}"
- "!**/node_modules/**"
- "!coverage/**"
- "!dist/**"
- "!build/**"

1
.dockerignore Normal file
View File

@@ -0,0 +1 @@
.git

View File

@@ -20,6 +20,6 @@
}
],
"@typescript-eslint/no-explicit-any": "off",
"no-undef": "off",
"no-undef": "off"
}
}

124
.github/DOCKER_CLI_TEST.md vendored Normal file
View File

@@ -0,0 +1,124 @@
# Docker Engine Installation Test Procedure
This document describes how to test the Docker Engine installation feature added with the `INSTALL_EXT=true` build argument.
## Test 1: Build with INSTALL_EXT=false (default)
```bash
# Build without extended features
docker build -t mcphub:base .
# Run the container
docker run --rm mcphub:base docker --version
```
**Expected Result**: `docker: not found` error (Docker is NOT installed)
## Test 2: Build with INSTALL_EXT=true
```bash
# Build with extended features
docker build --build-arg INSTALL_EXT=true -t mcphub:extended .
# Test Docker CLI is available
docker run --rm mcphub:extended docker --version
```
**Expected Result**: Docker version output (e.g., `Docker version 27.x.x, build xxxxx`)
## Test 3: Docker-in-Docker with Auto-start Daemon
```bash
# Build with extended features
docker build --build-arg INSTALL_EXT=true -t mcphub:extended .
# Run with privileged mode (allows Docker daemon to start)
docker run -d \
--name mcphub-test \
--privileged \
-p 3000:3000 \
mcphub:extended
# Wait a few seconds for daemon to start
sleep 5
# Test Docker commands from inside the container
docker exec mcphub-test docker ps
docker exec mcphub-test docker images
docker exec mcphub-test docker info
# Cleanup
docker stop mcphub-test
docker rm mcphub-test
```
**Expected Result**:
- Docker daemon should auto-start inside the container
- Docker commands should work without mounting the host's Docker socket
- `docker info` should show the container's own Docker daemon
## Test 4: Docker-in-Docker with Host Socket (Alternative)
```bash
# Build with extended features
docker build --build-arg INSTALL_EXT=true -t mcphub:extended .
# Run with Docker socket mounted (uses host's daemon)
docker run -d \
--name mcphub-test \
-p 3000:3000 \
-v /var/run/docker.sock:/var/run/docker.sock \
mcphub:extended
# Test Docker commands from inside the container
docker exec mcphub-test docker ps
docker exec mcphub-test docker images
# Cleanup
docker stop mcphub-test
docker rm mcphub-test
```
**Expected Result**:
- Docker daemon should NOT auto-start (socket already exists from host)
- Docker commands should work and show the host's containers and images
## Test 5: Verify Image Size
```bash
# Build both versions
docker build -t mcphub:base .
docker build --build-arg INSTALL_EXT=true -t mcphub:extended .
# Compare image sizes
docker images mcphub:*
```
**Expected Result**:
- The `extended` image should be larger than the `base` image
- The size difference should be reasonable (Docker Engine adds ~100-150MB)
## Test 6: Architecture Support
```bash
# On AMD64/x86_64
docker build --build-arg INSTALL_EXT=true --platform linux/amd64 -t mcphub:extended-amd64 .
# On ARM64
docker build --build-arg INSTALL_EXT=true --platform linux/arm64 -t mcphub:extended-arm64 .
```
**Expected Result**:
- Both builds should succeed
- AMD64 includes Chrome/Playwright + Docker Engine
- ARM64 includes Docker Engine only (Chrome installation is skipped)
## Notes
- The Docker Engine installation follows the official Docker documentation
- Includes full Docker daemon (`dockerd`), CLI (`docker`), and containerd
- The daemon auto-starts when running in privileged mode
- The installation uses the Debian Bookworm repository
- All temporary files are cleaned up to minimize image size
- The feature is opt-in via the `INSTALL_EXT` build argument
- `iptables` is installed as it's required for Docker networking

15
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: samanhappy
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@@ -0,0 +1,29 @@
---
name: Bug Report / Bug 报告
about: Create a report to help us improve / 报告问题以帮助改进
title: ''
labels: bug
assignees: ''
---
**Bug Description / 问题描述**
What happened? / 发生了什么?
**Steps to Reproduce / 复现步骤**
1.
2.
3.
**Expected Behavior / 预期行为**
What should happen? / 应该发生什么?
**Environment / 运行环境**
- Running on / 运行方式: [docker/npx/local / docker/npx/本地]
- Version / 版本: [e.g. 1.0.0]
**Screenshots / 截图**
If relevant, add screenshots / 如果有帮助的话,请添加截图
**Additional Info / 补充信息**
Any other details? / 还有其他信息吗?

View File

@@ -0,0 +1,20 @@
---
name: Feature request / 功能请求
about: Suggest an idea for this project / 为项目提出新想法
title: ''
labels: enhancement
assignees: ''
---
**Current Problem / 当前问题**
What problem are you trying to solve? / 您想要解决什么问题?
**Proposed Solution / 建议方案**
How would you like this to work? / 您期望的解决方案是什么?
**Alternatives / 替代方案**
Have you considered any alternatives? / 您是否考虑过其他解决方案?
**Additional Context / 补充说明**
Any screenshots, mockups, or relevant information? / 有任何截图、设计图或相关信息吗?

263
.github/copilot-instructions.md vendored Normal file
View File

@@ -0,0 +1,263 @@
# MCPHub Coding Instructions
**ALWAYS follow these instructions first and only fallback to additional search and context gathering if the information here is incomplete or found to be in error.**
## Project Overview
MCPHub is a TypeScript/Node.js MCP (Model Context Protocol) server management hub that provides unified access through HTTP endpoints. It serves as a centralized dashboard for managing multiple MCP servers with real-time monitoring, authentication, and flexible routing.
**Core Components:**
- **Backend**: Express.js + TypeScript + ESM (`src/server.ts`)
- **Frontend**: React/Vite + Tailwind CSS (`frontend/`)
- **MCP Integration**: Connects multiple MCP servers (`src/services/mcpService.ts`)
- **Authentication**: JWT-based with bcrypt password hashing
- **Configuration**: JSON-based MCP server definitions (`mcp_settings.json`)
- **Documentation**: API docs and usage instructions(`docs/`)
## Working Effectively
### Bootstrap and Setup (CRITICAL - Follow Exact Steps)
```bash
# Install pnpm if not available
npm install -g pnpm
# Install dependencies - takes ~30 seconds
pnpm install
# Setup environment (optional)
cp .env.example .env
# Build and test to verify setup
pnpm lint # ~3 seconds - NEVER CANCEL
pnpm backend:build # ~5 seconds - NEVER CANCEL
pnpm test:ci # ~16 seconds - NEVER CANCEL. Set timeout to 60+ seconds
pnpm frontend:build # ~5 seconds - NEVER CANCEL
pnpm build # ~10 seconds total - NEVER CANCEL. Set timeout to 60+ seconds
```
**CRITICAL TIMING**: These commands are fast but NEVER CANCEL them. Always wait for completion.
### Development Environment
```bash
# Start both backend and frontend (recommended for most development)
pnpm dev # Backend on :3001, Frontend on :5173
# OR start separately (required on Windows, optional on Linux/macOS)
# Terminal 1: Backend only
pnpm backend:dev # Runs on port 3000 (or PORT env var)
# Terminal 2: Frontend only
pnpm frontend:dev # Runs on port 5173, proxies API to backend
```
**NEVER CANCEL**: Development servers may take 10-15 seconds to fully initialize all MCP servers.
### Build Commands (Production)
```bash
# Full production build - takes ~10 seconds total
pnpm build # NEVER CANCEL - Set timeout to 60+ seconds
# Individual builds
pnpm backend:build # TypeScript compilation - ~5 seconds
pnpm frontend:build # Vite build - ~5 seconds
# Start production server
pnpm start # Requires dist/ and frontend/dist/ to exist
```
### Testing and Validation
```bash
# Run all tests - takes ~16 seconds with 73 tests
pnpm test:ci # NEVER CANCEL - Set timeout to 60+ seconds
# Development testing
pnpm test # Interactive mode
pnpm test:watch # Watch mode for development
pnpm test:coverage # With coverage report
# Code quality
pnpm lint # ESLint - ~3 seconds
pnpm format # Prettier formatting - ~3 seconds
```
**CRITICAL**: All tests MUST pass before committing. Do not modify tests to make them pass unless specifically required for your changes.
## Manual Validation Requirements
**ALWAYS perform these validation steps after making changes:**
### 1. Basic Application Functionality
```bash
# Start the application
pnpm dev
# Verify backend responds (in another terminal)
curl http://localhost:3000/api/health
# Expected: Should return health status
# Verify frontend serves
curl -I http://localhost:3000/
# Expected: HTTP 200 OK with HTML content
```
### 2. MCP Server Integration Test
```bash
# Check MCP servers are loading (look for log messages)
# Expected log output should include:
# - "Successfully connected client for server: [name]"
# - "Successfully listed [N] tools for server: [name]"
# - Some servers may fail due to missing API keys (normal in dev)
```
### 3. Build Verification
```bash
# Verify production build works
pnpm build
node scripts/verify-dist.js
# Expected: "✅ Verification passed! Frontend and backend dist files are present."
```
**NEVER skip these validation steps**. If any fail, debug and fix before proceeding.
## Project Structure and Key Files
### Critical Backend Files
- `src/index.ts` - Application entry point
- `src/server.ts` - Express server setup and middleware
- `src/services/mcpService.ts` - **Core MCP server management logic**
- `src/config/index.ts` - Configuration management
- `src/routes/` - HTTP route definitions
- `src/controllers/` - HTTP request handlers
- `src/dao/` - Data access layer for users, groups, servers
- `src/types/index.ts` - TypeScript type definitions
### Critical Frontend Files
- `frontend/src/` - React application source
- `frontend/src/pages/` - Page components (development entry point)
- `frontend/src/components/` - Reusable UI components
- `frontend/src/utils/fetchInterceptor.js` - Backend API interaction
### Configuration Files
- `mcp_settings.json` - **MCP server definitions and user accounts**
- `package.json` - Dependencies and scripts
- `tsconfig.json` - TypeScript configuration
- `jest.config.cjs` - Test configuration
- `.eslintrc.json` - Linting rules
### Docker and Deployment
- `Dockerfile` - Multi-stage build with Python base + Node.js
- `entrypoint.sh` - Docker startup script
- `bin/cli.js` - NPM package CLI entry point
## Development Process and Conventions
### Code Style Requirements
- **ESM modules**: Always use `.js` extensions in imports, not `.ts`
- **English only**: All code comments must be written in English
- **TypeScript strict**: Follow strict type checking rules
- **Import style**: `import { something } from './file.js'` (note .js extension)
### Key Configuration Notes
- **MCP servers**: Defined in `mcp_settings.json` with command/args
- **Endpoints**: `/mcp/{group|server}` and `/mcp/$smart` for routing
- **i18n**: Frontend uses react-i18next with files in `locales/` folder
- **Authentication**: JWT tokens with bcrypt password hashing
- **Default credentials**: admin/admin123 (configured in mcp_settings.json)
### Development Entry Points
- **Add MCP server**: Modify `mcp_settings.json` and restart
- **New API endpoint**: Add route in `src/routes/`, controller in `src/controllers/`
- **Frontend feature**: Start from `frontend/src/pages/` or `frontend/src/components/`
- **Add tests**: Follow patterns in `tests/` directory
### Common Development Tasks
#### Adding a new MCP server:
1. Add server definition to `mcp_settings.json`
2. Restart backend to load new server
3. Check logs for successful connection
4. Test via dashboard or API endpoints
#### API development:
1. Define route in `src/routes/`
2. Implement controller in `src/controllers/`
3. Add types in `src/types/index.ts` if needed
4. Write tests in `tests/controllers/`
#### Frontend development:
1. Create/modify components in `frontend/src/components/`
2. Add pages in `frontend/src/pages/`
3. Update routing if needed
4. Test in development mode with `pnpm frontend:dev`
#### Documentation:
1. Update or add docs in `docs/` folder
2. Ensure README.md reflects any major changes
## Validation and CI Requirements
### Before Committing - ALWAYS Run:
```bash
pnpm lint # Must pass - ~3 seconds
pnpm backend:build # Must compile - ~5 seconds
pnpm test:ci # All tests must pass - ~16 seconds
pnpm build # Full build must work - ~10 seconds
```
**CRITICAL**: CI will fail if any of these commands fail. Fix issues locally first.
### CI Pipeline (.github/workflows/ci.yml)
- Runs on Node.js 20.x
- Tests: linting, type checking, unit tests with coverage
- **NEVER CANCEL**: CI builds may take 2-3 minutes total
## Troubleshooting
### Common Issues
- **"uvx command not found"**: Some MCP servers require `uvx` (Python package manager) - this is expected in development
- **Port already in use**: Change PORT environment variable or kill existing processes
- **Frontend not loading**: Ensure frontend was built with `pnpm frontend:build`
- **MCP server connection failed**: Check server command/args in `mcp_settings.json`
### Build Failures
- **TypeScript errors**: Run `pnpm backend:build` to see compilation errors
- **Test failures**: Run `pnpm test:verbose` for detailed test output
- **Lint errors**: Run `pnpm lint` and fix reported issues
### Development Issues
- **Backend not starting**: Check for port conflicts, verify `mcp_settings.json` syntax
- **Frontend proxy errors**: Ensure backend is running before starting frontend
- **Hot reload not working**: Restart development server
## Performance Notes
- **Install time**: pnpm install takes ~30 seconds
- **Build time**: Full build takes ~10 seconds
- **Test time**: Complete test suite takes ~16 seconds
- **Startup time**: Backend initialization takes 10-15 seconds (MCP server connections)
**Remember**: NEVER CANCEL any build or test commands. Always wait for completion even if they seem slow.

11
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "monthly"

View File

@@ -8,6 +8,9 @@ on:
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
matrix:
variant: ${{ startsWith(github.ref, 'refs/tags/') && fromJSON('["base", "full"]') || fromJSON('["base"]') }}
@@ -16,28 +19,50 @@ jobs:
with:
fetch-depth: 0
- name: Update version from tag
if: startsWith(github.ref, 'refs/tags/')
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "Updating package.json version to $VERSION"
jq ".version = \"$VERSION\"" package.json > package.json.tmp
mv package.json.tmp package.json
echo "Updated version in package.json:"
grep -m 1 "version" package.json
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
if: endsWith(github.repository, 'mcphub')
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
if: endsWith(github.repository, 'mcphubx')
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: samanhappy/mcphub
images: |
${{ endsWith(github.repository, 'mcphub') && github.repository || '' }}
${{ endsWith(github.repository, 'mcphubx') && format('ghcr.io/{0}', github.repository) || '' }}
tags: |
type=raw,value=edge${{ matrix.variant == 'full' && '-full' || '' }},enable=${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }}
type=semver,pattern={{version}}${{ matrix.variant == 'full' && '-full' || '' }},enable=${{ startsWith(github.ref, 'refs/tags/') }}
type=raw,value=latest${{ matrix.variant == 'full' && '-full' || '' }},enable=${{ startsWith(github.ref, 'refs/tags/') }}
flavor: |
latest=false
- name: Build and Push Docker Image
if: endsWith(github.repository, 'mcphub') || endsWith(github.repository, 'mcphubx')
uses: docker/build-push-action@v5
with:
context: .

112
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,112 @@
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.x]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Enable Corepack
run: corepack enable
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Run linter
run: pnpm lint
- name: Run type checking
run: pnpm backend:build
- name: Run tests
run: pnpm test:ci
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage/lcov.info
flags: unittests
name: codecov-umbrella
# build:
# runs-on: ubuntu-latest
# needs: test
# steps:
# - name: Checkout code
# uses: actions/checkout@v4
# - name: Setup Node.js
# uses: actions/setup-node@v4
# with:
# node-version: '20.x'
# - name: Enable Corepack
# run: corepack enable
# - name: Install dependencies
# run: pnpm install --frozen-lockfile
# - name: Build application
# run: pnpm build
# - name: Verify build artifacts
# run: node scripts/verify-dist.js
# integration-test:
# runs-on: ubuntu-latest
# needs: test
# services:
# postgres:
# image: postgres:15
# env:
# POSTGRES_PASSWORD: postgres
# POSTGRES_DB: mcphub_test
# options: >-
# --health-cmd pg_isready
# --health-interval 10s
# --health-timeout 5s
# --health-retries 5
# steps:
# - name: Checkout code
# uses: actions/checkout@v4
# - name: Setup Node.js
# uses: actions/setup-node@v4
# with:
# node-version: '20.x'
# - name: Enable Corepack
# run: corepack enable
# - name: Install dependencies
# run: pnpm install --frozen-lockfile
# - name: Build application
# run: pnpm build
# - name: Run integration tests
# run: |
# export DATABASE_URL="postgresql://postgres:postgres@localhost:5432/mcphub_test"
# node test-integration.ts
# env:
# NODE_ENV: test

59
.github/workflows/npm-publish.yml vendored Normal file
View File

@@ -0,0 +1,59 @@
name: Publish to NPM
on:
push:
tags: ['v*.*.*']
jobs:
publish-npm:
runs-on: ubuntu-latest
if: endsWith(github.repository, 'mcphub')
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 10
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Setup pnpm cache
uses: actions/cache@v4
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Update version from tag
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "Updating package.json version to $VERSION"
jq ".version = \"$VERSION\"" package.json > package.json.tmp
mv package.json.tmp package.json
echo "Updated version in package.json:"
grep -m 1 "version" package.json
- name: Build package
run: pnpm build
- name: Publish to NPM
run: pnpm publish --no-git-checks --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -13,6 +13,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Release
uses: softprops/action-gh-release@v2
with:

4
.gitignore vendored
View File

@@ -2,6 +2,7 @@
/node_modules
/.pnp
.pnp.js
package-lock.json
# production
dist
@@ -24,3 +25,6 @@ yarn-error.log*
.vscode/
*.log
coverage/
data/
temp-test-config/

View File

@@ -4,4 +4,4 @@
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2
}
}

30
AGENTS.md Normal file
View File

@@ -0,0 +1,30 @@
# Repository Guidelines
These notes align current contributors around the code layout, daily commands, and collaboration habits that keep `@samanhappy/mcphub` moving quickly.
## Project Structure & Module Organization
- Backend services live in `src`, grouped by responsibility (`controllers/`, `services/`, `dao/`, `routes/`, `utils/`), with `server.ts` orchestrating HTTP bootstrap.
- `frontend/src` contains the Vite + React dashboard; `frontend/public` hosts static assets and translations sit in `locales/`.
- Jest-aware test code is split between colocated specs (`src/**/*.{test,spec}.ts`) and higher-level suites in `tests/`; use `tests/utils/` helpers when exercising the CLI or SSE flows.
- Build artifacts and bundles are generated into `dist/`, `frontend/dist/`, and `coverage/`; never edit these manually.
## Build, Test, and Development Commands
- `pnpm dev` runs backend (`tsx watch src/index.ts`) and frontend (`vite`) together for local iteration.
- `pnpm backend:dev`, `pnpm frontend:dev`, and `pnpm frontend:preview` target each surface independently; prefer them when debugging one stack.
- `pnpm build` executes `pnpm backend:build` (TypeScript to `dist/`) and `pnpm frontend:build`; run before release or publishing.
- `pnpm test`, `pnpm test:watch`, and `pnpm test:coverage` drive Jest; `pnpm lint` and `pnpm format` enforce style via ESLint and Prettier.
## Coding Style & Naming Conventions
- TypeScript everywhere; default to 2-space indentation and single quotes, letting Prettier settle formatting. ESLint configuration assumes ES modules.
- Name services and data access layers with suffixes (`UserService`, `AuthDao`), React components and files in `PascalCase`, and utility modules in `camelCase`.
- Keep DTOs and shared types in `src/types` to avoid duplication; re-export through index files only when it clarifies imports.
## Testing Guidelines
- Use Jest with the `ts-jest` ESM preset; place shared setup in `tests/setup.ts` and mock helpers under `tests/utils/`.
- Mirror production directory names when adding new suites and end filenames with `.test.ts` or `.spec.ts` for automatic discovery.
- Aim to maintain or raise coverage when touching critical flows (auth, OAuth, SSE); add integration tests under `tests/integration/` when touching cross-service logic.
## Commit & Pull Request Guidelines
- Follow the existing Conventional Commit pattern (`feat:`, `fix:`, `chore:`, etc.) with imperative, present-tense summaries and optional multi-line context.
- Each PR should describe the behavior change, list testing performed, and link issues; include before/after screenshots or GIFs for frontend tweaks.
- Re-run `pnpm build` and `pnpm test` before requesting review, and ensure generated artifacts stay out of the diff.

View File

@@ -9,26 +9,32 @@ RUN apt-get update && apt-get install -y curl gnupg git \
RUN npm install -g pnpm
ARG REQUEST_TIMEOUT=60000
ENV REQUEST_TIMEOUT=$REQUEST_TIMEOUT
ENV PNPM_HOME=/usr/local/share/pnpm
ENV PATH=$PNPM_HOME:$PATH
RUN mkdir -p $PNPM_HOME && \
pnpm add -g @amap/amap-maps-mcp-server @playwright/mcp@latest tavily-mcp@latest @modelcontextprotocol/server-github @modelcontextprotocol/server-slack
pnpm add -g @amap/amap-maps-mcp-server @playwright/mcp@latest tavily-mcp@latest @modelcontextprotocol/server-github @modelcontextprotocol/server-slack
ARG INSTALL_EXT=false
RUN if [ "$INSTALL_EXT" = "true" ]; then \
ARCH=$(uname -m); \
if [ "$ARCH" = "x86_64" ]; then \
npx -y playwright install --with-deps chrome; \
else \
echo "Skipping Chrome installation on non-amd64 architecture: $ARCH"; \
fi; \
fi
ARCH=$(uname -m); \
if [ "$ARCH" = "x86_64" ]; then \
npx -y playwright install --with-deps chrome; \
else \
echo "Skipping Chrome installation on non-amd64 architecture: $ARCH"; \
fi; \
# Install Docker Engine (includes CLI and daemon) \
apt-get update && \
apt-get install -y ca-certificates curl iptables && \
install -m 0755 -d /etc/apt/keyrings && \
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc && \
chmod a+r /etc/apt/keyrings/docker.asc && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian bookworm stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null && \
apt-get update && \
apt-get install -y docker-ce docker-ce-cli containerd.io && \
apt-get clean && rm -rf /var/lib/apt/lists/*; \
fi
RUN uv tool install mcp-server-fetch
ENV UV_PYTHON_INSTALL_MIRROR="http://mirrors.aliyun.com/pypi/simple/"
WORKDIR /app

126
QWEN.md Normal file
View File

@@ -0,0 +1,126 @@
# MCPHub Project Overview
## Project Summary
MCPHub is a centralized hub server for managing multiple Model Context Protocol (MCP) servers. It allows organizing these servers into flexible Streamable HTTP (SSE) endpoints, supporting access to all servers, individual servers, or logical server groups. It provides a web dashboard for monitoring and managing servers, along with features like authentication, group-based access control, and Smart Routing using vector semantic search.
## Technology Stack
### Backend
- **Language:** TypeScript (Node.js)
- **Framework:** Express
- **Key Libraries:**
- `@modelcontextprotocol/sdk`: Core library for MCP interactions.
- `typeorm`: ORM for database interactions.
- `pg` & `pgvector`: PostgreSQL database and vector support.
- `jsonwebtoken` & `bcryptjs`: Authentication (JWT) and password hashing.
- `openai`: For embedding generation in Smart Routing.
- Various utility and validation libraries (e.g., `dotenv`, `express-validator`, `uuid`).
### Frontend
- **Framework:** React (via Vite)
- **Language:** TypeScript
- **UI Library:** Tailwind CSS
- **Routing:** `react-router-dom`
- **Internationalization:** `i18next`
- **Component Structure:** Modular components and pages within `frontend/src`.
### Infrastructure
- **Build Tool:** `pnpm` (package manager and script runner).
- **Containerization:** Docker (`Dockerfile` provided).
- **Process Management:** Not explicitly defined in core files, but likely managed by Docker or host system.
## Key Features
- **MCP Server Management:** Configure, start, stop, and monitor multiple upstream MCP servers via `stdio`, `SSE`, or `Streamable HTTP` protocols.
- **Centralized Dashboard:** Web UI for server status, group management, user administration, and logs.
- **Flexible Endpoints:**
- Global MCP/SSE endpoint (`/mcp`, `/sse`) for all enabled servers.
- Group-based endpoints (`/mcp/{group}`, `/sse/{group}`).
- Server-specific endpoints (`/mcp/{server}`, `/sse/{server}`).
- Smart Routing endpoint (`/mcp/$smart`, `/sse/$smart`) using vector search.
- **Authentication & Authorization:** JWT-based user authentication with role-based access control (admin/user).
- **Group Management:** Logical grouping of servers for targeted access and permission control.
- **Smart Routing (Experimental):** Uses pgvector and OpenAI embeddings to semantically search and find relevant tools across all connected servers.
- **Configuration:** Managed via `mcp_settings.json`.
- **Logging:** Server logs are captured and viewable via the dashboard.
- **Marketplace Integration:** Access to a marketplace of MCP servers (`servers.json`).
## Project Structure
```
C:\code\mcphub\
├───src\ # Backend source code (TypeScript)
├───frontend\ # Frontend source code (React/TypeScript)
│ ├───src\
│ ├───components\ # Reusable UI components
│ ├───pages\ # Top-level page components
│ ├───contexts\ # React contexts (Auth, Theme, Toast)
│ ├───layouts\ # Page layouts
│ ├───utils\ # Frontend utilities
│ └───...
├───dist\ # Compiled backend output
├───frontend\dist\ # Compiled frontend output
├───tests\ # Backend tests
├───docs\ # Documentation
├───scripts\ # Utility scripts
├───bin\ # CLI entry points
├───assets\ # Static assets (e.g., images for README)
├───.github\ # GitHub workflows
├───.vscode\ # VS Code settings
├───mcp_settings.json # Main configuration file for MCP servers and users
├───servers.json # Marketplace server definitions
├───package.json # Node.js project definition, dependencies, and scripts
├───pnpm-lock.yaml # Dependency lock file
├───tsconfig.json # TypeScript compiler configuration (Backend)
├───README.md # Project documentation
├───Dockerfile # Docker image definition
└───...
```
## Building and Running
### Prerequisites
- Node.js (>=18.0.0 or >=20.0.0)
- pnpm
- Python 3.13 (for some upstream servers and uvx)
- Docker (optional, for containerized deployment)
- PostgreSQL with pgvector (optional, for Smart Routing)
### Local Development
1. Clone the repository.
2. Install dependencies: `pnpm install`.
3. Start development servers: `pnpm dev`.
- This runs `pnpm backend:dev` (Node.js with `tsx watch`) and `pnpm frontend:dev` (Vite dev server) concurrently.
- Access the dashboard at `http://localhost:5173` (Vite default) or the configured port/path.
### Production Build
1. Install dependencies: `pnpm install`.
2. Build the project: `pnpm build`.
- This runs `pnpm backend:build` (TypeScript compilation to `dist/`) and `pnpm frontend:build` (Vite build to `frontend/dist/`).
3. Start the production server: `pnpm start`.
- This runs `node dist/index.js`.
### Docker Deployment
- Pull the image: `docker pull samanhappy/mcphub`.
- Run with default settings: `docker run -p 3000:3000 samanhappy/mcphub`.
- Run with custom config: `docker run -p 3000:3000 -v ./mcp_settings.json:/app/mcp_settings.json -v ./data:/app/data samanhappy/mcphub`.
- Access the dashboard at `http://localhost:3000`.
## Configuration
The main configuration file is `mcp_settings.json`. It defines:
- `mcpServers`: A map of server configurations (command, args, env, URL, etc.).
- `users`: A list of user accounts (username, hashed password, admin status).
- `groups`: A map of server groups.
- `systemConfig`: System-wide settings (e.g., proxy, registry, installation options).
## Development Conventions
- **Language:** TypeScript for both backend and frontend.
- **Backend Style:** Modular structure with clear separation of concerns (controllers, services, models, middlewares, routes, config, utils).
- **Frontend Style:** Component-based React architecture with contexts for state management.
- **Database:** TypeORM with PostgreSQL is used, leveraging decorators for entity definition.
- **Testing:** Uses `jest` for backend testing.
- **Linting/Formatting:** Uses `eslint` and `prettier`.
- **Scripts:** Defined in `package.json` under the `scripts` section for common tasks (dev, build, start, test, lint, format).

235
README.fr.md Normal file
View File

@@ -0,0 +1,235 @@
[English](README.md) | Français | [中文版](README.zh.md)
# MCPHub : Le Hub Unifié pour les Serveurs MCP (Model Context Protocol)
MCPHub facilite la gestion et la mise à l'échelle de plusieurs serveurs MCP (Model Context Protocol) en les organisant en points de terminaison HTTP streamables (SSE) flexibles, prenant en charge l'accès à tous les serveurs, à des serveurs individuels ou à des groupes de serveurs logiques.
![Aperçu du tableau de bord](assets/dashboard.zh.png)
## 🌐 Démo en direct et Documentation
- **Documentation** : [docs.mcphubx.com](https://docs.mcphubx.com/)
- **Environnement de démo** : [demo.mcphubx.com](https://demo.mcphubx.com/)
## 🚀 Fonctionnalités
- **Support étendu des serveurs MCP** : Intégrez de manière transparente n'importe quel serveur MCP avec une configuration minimale.
- **Tableau de bord centralisé** : Surveillez l'état en temps réel et les métriques de performance depuis une interface web élégante.
- **Gestion flexible des protocoles** : Compatibilité totale avec les protocoles MCP stdio et SSE.
- **Configuration à chaud** : Ajoutez, supprimez ou mettez à jour les serveurs MCP à la volée, sans temps d'arrêt.
- **Contrôle d'accès basé sur les groupes** : Organisez les serveurs en groupes personnalisables pour une gestion simplifiée des autorisations.
- **Authentification sécurisée** : Gestion des utilisateurs intégrée avec contrôle d'accès basé sur les rôles, optimisée par JWT et bcrypt.
- **Prêt pour Docker** : Déployez instantanément avec notre configuration conteneurisée.
## 🔧 Démarrage rapide
### Configuration
Créez un fichier `mcp_settings.json` pour personnaliser les paramètres de votre serveur :
```json
{
"mcpServers": {
"amap": {
"command": "npx",
"args": ["-y", "@amap/amap-maps-mcp-server"],
"env": {
"AMAP_MAPS_API_KEY": "votre-clé-api"
}
},
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest", "--headless"]
},
"fetch": {
"command": "uvx",
"args": ["mcp-server-fetch"]
},
"slack": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-slack"],
"env": {
"SLACK_BOT_TOKEN": "votre-jeton-bot",
"SLACK_TEAM_ID": "votre-id-équipe"
}
}
}
}
```
### Déploiement avec Docker
**Recommandé** : Montez votre configuration personnalisée :
```bash
docker run -p 3000:3000 -v ./mcp_settings.json:/app/mcp_settings.json -v ./data:/app/data samanhappy/mcphub
```
Ou exécutez avec les paramètres par défaut :
```bash
docker run -p 3000:3000 samanhappy/mcphub
```
### Accéder au tableau de bord
Ouvrez `http://localhost:3000` et connectez-vous avec vos identifiants.
> **Note** : Les identifiants par défaut sont `admin` / `admin123`.
**Aperçu du tableau de bord** :
- État en direct de tous les serveurs MCP
- Activer/désactiver ou reconfigurer les serveurs
- Gestion des groupes pour organiser les serveurs
- Administration des utilisateurs pour le contrôle d'accès
### Point de terminaison HTTP streamable
> Pour le moment, la prise en charge des points de terminaison HTTP en streaming varie selon les clients IA. Si vous rencontrez des problèmes, vous pouvez utiliser le point de terminaison SSE ou attendre les futures mises à jour.
Connectez les clients IA (par exemple, Claude Desktop, Cursor, DeepChat, etc.) via :
```
http://localhost:3000/mcp
```
Ce point de terminaison fournit une interface HTTP streamable unifiée pour tous vos serveurs MCP. Il vous permet de :
- Envoyer des requêtes à n'importe quel serveur MCP configuré
- Recevoir des réponses en temps réel
- Intégrer facilement avec divers clients et outils IA
- Utiliser le même point de terminaison pour tous les serveurs, simplifiant votre processus d'intégration
**Routage intelligent (expérimental)** :
Le routage intelligent est le système de découverte d'outils intelligent de MCPHub qui utilise la recherche sémantique vectorielle pour trouver automatiquement les outils les plus pertinents pour une tâche donnée.
```
http://localhost:3000/mcp/$smart
```
**Comment ça marche** :
1. **Indexation des outils** : Tous les outils MCP sont automatiquement convertis en plongements vectoriels et stockés dans PostgreSQL avec pgvector.
2. **Recherche sémantique** : Les requêtes des utilisateurs sont converties en vecteurs et comparées aux plongements des outils en utilisant la similarité cosinus.
3. **Filtrage intelligent** : Des seuils dynamiques garantissent des résultats pertinents sans bruit.
4. **Exécution précise** : Les outils trouvés peuvent être directement exécutés avec une validation appropriée des paramètres.
**Prérequis pour la configuration** :
![Routage intelligent](assets/smart-routing.zh.png)
Pour activer le routage intelligent, vous avez besoin de :
- PostgreSQL avec l'extension pgvector
- Une clé API OpenAI (ou un service de plongement compatible)
- Activer le routage intelligent dans les paramètres de MCPHub
**Points de terminaison spécifiques aux groupes (recommandé)** :
![Gestion des groupes](assets/group.zh.png)
Pour un accès ciblé à des groupes de serveurs spécifiques, utilisez le point de terminaison HTTP basé sur les groupes :
```
http://localhost:3000/mcp/{group}
```
`{group}` est l'ID ou le nom du groupe que vous avez créé dans le tableau de bord. Cela vous permet de :
- Vous connecter à un sous-ensemble spécifique de serveurs MCP organisés par cas d'utilisation
- Isoler différents outils IA pour n'accéder qu'aux serveurs pertinents
- Mettre en œuvre un contrôle d'accès plus granulaire pour différents environnements ou équipes
**Points de terminaison spécifiques aux serveurs** :
Pour un accès direct à des serveurs individuels, utilisez le point de terminaison HTTP spécifique au serveur :
```
http://localhost:3000/mcp/{server}
```
`{server}` est le nom du serveur auquel vous souhaitez vous connecter. Cela vous permet d'accéder directement à un serveur MCP spécifique.
> **Note** : Si le nom du serveur et le nom du groupe sont identiques, le nom du groupe aura la priorité.
### Point de terminaison SSE (obsolète à l'avenir)
Connectez les clients IA (par exemple, Claude Desktop, Cursor, DeepChat, etc.) via :
```
http://localhost:3000/sse
```
Pour le routage intelligent, utilisez :
```
http://localhost:3000/sse/$smart
```
Pour un accès ciblé à des groupes de serveurs spécifiques, utilisez le point de terminaison SSE basé sur les groupes :
```
http://localhost:3000/sse/{group}
```
Pour un accès direct à des serveurs individuels, utilisez le point de terminaison SSE spécifique au serveur :
```
http://localhost:3000/sse/{server}
```
## 🧑‍💻 Développement local
```bash
git clone https://github.com/samanhappy/mcphub.git
cd mcphub
pnpm install
pnpm dev
```
Cela démarre à la fois le frontend et le backend en mode développement avec rechargement à chaud.
> Pour les utilisateurs de Windows, vous devrez peut-être démarrer le serveur backend et le frontend séparément : `pnpm backend:dev`, `pnpm frontend:dev`.
## 🛠️ Problèmes courants
### Utiliser Nginx comme proxy inverse
Si vous utilisez Nginx pour inverser le proxy de MCPHub, assurez-vous d'ajouter la configuration suivante dans votre configuration Nginx :
```nginx
proxy_buffering off
```
## 🔍 Stack technique
- **Backend** : Node.js, Express, TypeScript
- **Frontend** : React, Vite, Tailwind CSS
- **Authentification** : JWT & bcrypt
- **Protocole** : Model Context Protocol SDK
## 👥 Contribuer
Les contributions de toute nature sont les bienvenues !
- Nouvelles fonctionnalités et optimisations
- Améliorations de la documentation
- Rapports de bugs et corrections
- Traductions et suggestions
Rejoignez notre [communauté Discord](https://discord.gg/qMKNsn5Q) pour des discussions et du soutien.
## ❤️ Sponsor
Si vous aimez ce projet, vous pouvez peut-être envisager de :
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/samanhappy)
## 🌟 Historique des étoiles
[![Historique des étoiles](https://api.star-history.com/svg?repos=samanhappy/mcphub&type=Date)](https://www.star-history.com/#samanhappy/mcphub&Date)
## 📄 Licence
Sous licence [Apache 2.0 License](LICENSE).

249
README.md
View File

@@ -1,24 +1,33 @@
# MCPHub: Your Ultimate MCP Server Hub
# MCPHub: The Unified Hub for Model Context Protocol (MCP) Servers
English | [中文版](README.zh.md)
English | [Français](README.fr.md) | [中文版](README.zh.md)
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.
MCPHub makes it easy to manage and scale multiple MCP (Model Context Protocol) servers by organizing them into flexible Streamable HTTP (SSE) endpoints—supporting access to all servers, individual servers, or logical server groups.
![Dashboard Preview](assets/dashboard.png)
## 🌐 Live Demo & Docs
- **Documentation**: [docs.mcphubx.com](https://docs.mcphubx.com/)
- **Demo Environment**: [demo.mcphubx.com](https://demo.mcphubx.com/)
## 🚀 Features
- **Out-of-the-Box MCP Server Support**: Seamlessly integrate popular servers like `amap-maps`, `playwright`, `fetch`, `slack`, and more.
- **Broadened MCP Server Support**: Seamlessly integrate any MCP server with minimal configuration.
- **Centralized Dashboard**: Monitor real-time status and performance metrics from one sleek web UI.
- **Flexible Protocol Handling**: Full compatibility with both stdio and SSE MCP protocols.
- **Hot-Swappable Configuration**: Add, remove, or update MCP servers on the fly — no downtime required.
- **Group-Based Access Control**: Organize servers into customizable groups for streamlined permissions management.
- **Secure Authentication**: Built-in user management with role-based access powered by JWT and bcrypt.
- **OAuth 2.0 Support**:
- Full OAuth support for upstream MCP servers with proxy authorization capabilities
- **NEW**: Act as OAuth 2.0 authorization server for external clients (ChatGPT Web, custom apps)
- **Environment Variable Expansion**: Use environment variables anywhere in your configuration for secure credential management. See [Environment Variables Guide](docs/environment-variables.md).
- **Docker-Ready**: Deploy instantly with our containerized setup.
## 🔧 Quick Start
### Optional Configuration
### Configuration
Create a `mcp_settings.json` file to customize your server settings:
@@ -48,31 +57,95 @@ Create a `mcp_settings.json` file to customize your server settings:
"SLACK_TEAM_ID": "your-team-id"
}
}
}
}
```
#### OAuth Configuration (Optional)
MCPHub supports OAuth 2.0 for authenticating with upstream MCP servers. See the [OAuth feature guide](docs/features/oauth.mdx) for a full walkthrough. In practice you will run into two configuration patterns:
- **Dynamic registration servers** (e.g., Vercel, Linear) publish all metadata and allow MCPHub to self-register. Simply declare the server URL and MCPHub handles the rest.
- **Manually provisioned servers** (e.g., GitHub Copilot) require you to create an OAuth App and provide the issued client ID/secret to MCPHub.
Dynamic registration example:
```json
{
"mcpServers": {
"vercel": {
"type": "sse",
"url": "https://mcp.vercel.com"
}
}
}
```
Manual registration example:
```json
{
"mcpServers": {
"github": {
"type": "sse",
"url": "https://api.githubcopilot.com/mcp/",
"oauth": {
"clientId": "${GITHUB_OAUTH_APP_ID}",
"clientSecret": "${GITHUB_OAUTH_APP_SECRET}"
}
}
}
}
```
For manual providers, create the OAuth App in the upstream console, set the redirect URI to `http://localhost:3000/oauth/callback` (or your deployed domain), and then plug the credentials into the dashboard or config file.
#### OAuth Authorization Server (NEW)
MCPHub can now act as an OAuth 2.0 authorization server, allowing external applications to securely access your MCP servers using standard OAuth flows. This is particularly useful for integrating with ChatGPT Web and other services that require OAuth authentication.
**Enable OAuth Server:**
```json
{
"systemConfig": {
"oauthServer": {
"enabled": true,
"accessTokenLifetime": 3600,
"refreshTokenLifetime": 1209600,
"allowedScopes": ["read", "write"]
}
},
"users": [
"oauthClients": [
{
"username": "admin",
"password": "$2b$10$Vt7krIvjNgyN67LXqly0uOcTpN0LI55cYRbcKC71pUDAP0nJ7RPa.",
"isAdmin": true
"clientId": "your-client-id",
"name": "ChatGPT Web",
"redirectUris": ["https://chatgpt.com/oauth/callback"],
"grants": ["authorization_code", "refresh_token"],
"scopes": ["read", "write"]
}
]
}
```
> **Note**: Default credentials are `admin` / `admin123`. Passwords are securely hashed with bcrypt. Generate a new hash with:
>
> ```bash
> npx bcryptjs your-password
> ```
**Key Features:**
- Standard OAuth 2.0 authorization code flow
- PKCE support for enhanced security
- Token refresh capabilities
- Compatible with ChatGPT Web and other OAuth clients
For detailed setup instructions, see the [OAuth Server Documentation](docs/oauth-server.md).
### Docker Deployment
**Recommended**: Mount your custom config:
```bash
docker run -p 3000:3000 -v $(pwd)/mcp_settings.json:/app/mcp_settings.json samanhappy/mcphub
docker run -p 3000:3000 -v ./mcp_settings.json:/app/mcp_settings.json -v ./data:/app/data samanhappy/mcphub
```
or run with default settings:
```bash
docker run -p 3000:3000 samanhappy/mcphub
```
@@ -80,34 +153,136 @@ docker run -p 3000:3000 samanhappy/mcphub
### Access the Dashboard
Open `http://localhost:3000` and log in with your credentials.
> **Note**: Default credentials are `admin` / `admin123`.
**Dashboard Overview**:
- Live status of all MCP servers
- Enable/disable or reconfigure servers
- Group management for organizing servers
- User administration for access control
### SSE Endpoint
### Streamable HTTP Endpoint
> 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.
Connect AI clients (e.g., Claude Desktop, Cursor, DeepChat, etc.) via:
```
http://localhost:3000/mcp
```
This endpoint provides a unified streamable HTTP interface for all your MCP servers. It allows you to:
- Send requests to any configured MCP server
- Receive responses in real-time
- Easily integrate with various AI clients and tools
- Use the same endpoint for all servers, simplifying your integration process
**Smart Routing (Experimental)**:
Smart Routing is MCPHub's intelligent tool discovery system that uses vector semantic search to automatically find the most relevant tools for any given task.
```
# Search across all servers
http://localhost:3000/mcp/$smart
# Search within a specific group
http://localhost:3000/mcp/$smart/{group}
```
**How it Works:**
1. **Tool Indexing**: All MCP tools are automatically converted to vector embeddings and stored in PostgreSQL with pgvector
2. **Semantic Search**: User queries are converted to vectors and matched against tool embeddings using cosine similarity
3. **Intelligent Filtering**: Dynamic thresholds ensure relevant results without noise
4. **Precise Execution**: Found tools can be directly executed with proper parameter validation
5. **Group Scoping**: Optionally limit searches to servers within a specific group for focused results
**Setup Requirements:**
![Smart Routing](assets/smart-routing.png)
To enable Smart Routing, you need:
- PostgreSQL with pgvector extension
- OpenAI API key (or compatible embedding service)
- Enable Smart Routing in MCPHub settings
**Group-Scoped Smart Routing**:
You can combine Smart Routing with group filtering to search only within specific server groups:
```
# Search only within production servers
http://localhost:3000/mcp/$smart/production
# Search only within development servers
http://localhost:3000/mcp/$smart/development
```
This enables:
- **Focused Discovery**: Find tools only from relevant servers
- **Environment Isolation**: Separate tool discovery by environment (dev, staging, prod)
- **Team-Based Access**: Limit tool search to team-specific server groups
**Group-Specific Endpoints (Recommended)**:
![Group Management](assets/group.png)
For targeted access to specific server groups, use the group-based HTTP endpoint:
```
http://localhost:3000/mcp/{group}
```
Where `{group}` is the ID or name of the group you created in the dashboard. This allows you to:
- Connect to a specific subset of MCP servers organized by use case
- Isolate different AI tools to access only relevant servers
- Implement more granular access control for different environments or teams
**Server-Specific Endpoints**:
For direct access to individual servers, use the server-specific HTTP endpoint:
```
http://localhost:3000/mcp/{server}
```
Where `{server}` is the name of the server you want to connect to. This allows you to access a specific MCP server directly.
> **Note**: If the server name and group name are the same, the group name will take precedence.
### SSE Endpoint (Deprecated in Future)
Connect AI clients (e.g., Claude Desktop, Cursor, DeepChat, etc.) via:
Connect AI clients (e.g., Claude Desktop, Cursor, Cherry Studio) via:
```
http://localhost:3000/sse
```
**Group-Specific Endpoints (Recommended)**:
For smart routing, use:
![Group Management](assets/group.png)
```
# Search across all servers
http://localhost:3000/sse/$smart
# Search within a specific group
http://localhost:3000/sse/$smart/{group}
```
For targeted access to specific server groups, use the group-based SSE endpoint:
```
http://localhost:3000/sse/{groupId}
http://localhost:3000/sse/{group}
```
Where `{groupId}` is the ID of the group you created in the dashboard. This allows you to:
- Connect to a specific subset of MCP servers organized by use case
- Isolate different AI tools to access only relevant servers
- Implement more granular access control for different environments or teams
For direct access to individual servers, use the server-specific SSE endpoint:
```
http://localhost:3000/sse/{server}
```
## 🧑‍💻 Local Development
@@ -120,6 +295,18 @@ pnpm dev
This starts both frontend and backend in development mode with hot-reloading.
> For windows users, you may need to start the backend server and frontend separately: `pnpm backend:dev`, `pnpm frontend:dev`.
## 🛠️ Common Issues
### Using Nginx as a Reverse Proxy
If you are using Nginx to reverse proxy MCPHub, please make sure to add the following configuration in your Nginx setup:
```nginx
proxy_buffering off
```
## 🔍 Tech Stack
- **Backend**: Node.js, Express, TypeScript
@@ -129,13 +316,25 @@ This starts both frontend and backend in development mode with hot-reloading.
## 👥 Contributing
Contributions are welcome!
Contributions of any kind are welcome!
- New features & optimizations
- Documentation improvements
- Bug reports & fixes
- Translations & suggestions
Welcome to join our [Discord community](https://discord.gg/qMKNsn5Q) for discussions and support.
## ❤️ Sponsor
If you like this project, maybe you can consider:
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/samanhappy)
## 🌟 Star History
[![Star History Chart](https://api.star-history.com/svg?repos=samanhappy/mcphub&type=Date)](https://www.star-history.com/#samanhappy/mcphub&Date)
## 📄 License
Licensed under the [Apache 2.0 License](LICENSE).

View File

@@ -1,14 +1,19 @@
# MCPHub一站式 MCP 服务器聚合平台
[English Version](README.md) | 中文版
[English](README.md) | [Français](README.fr.md) | 中文版
MCPHub 是一个统一的 MCPModel Context Protocol,模型上下文协议)服务器聚合平台,可以根据场景将多个服务器聚合到不同的 SSE 端点。它通过直观的界面和强大的协议处理能力,简化了您的 AI 工具集成流程
MCPHub 通过将多个 MCPModel Context Protocol)服务器组织为灵活的流式 HTTPSSE端点,简化了管理与扩展工作。系统支持按需访问全部服务器、单个服务器或按场景分组的服务器集合
![控制面板预览](assets/dashboard.zh.png)
## 🌐 在线文档与演示
- **文档地址**: [docs.mcphubx.com](https://docs.mcphubx.com/)
- **演示环境**: [demo.mcphubx.com](https://demo.mcphubx.com/)
## 🚀 功能亮点
- **开箱即用的 MCP 服务器支持**:无缝集成 `amap-maps``playwright``fetch``slack` 等常见服务器
- **广泛的 MCP 服务器支持**:无缝集成任何 MCP 服务器,配置简单
- **集中式管理控制台**:在一个简洁的 Web UI 中实时监控所有服务器的状态和性能指标。
- **灵活的协议兼容**:完全支持 stdio 和 SSE 两种 MCP 协议。
- **热插拔式配置**:在运行时动态添加、移除或更新服务器配置,无需停机。
@@ -18,7 +23,7 @@ MCPHub 是一个统一的 MCPModel Context Protocol模型上下文协议
## 🔧 快速开始
### 可选配置
### 配置
通过创建 `mcp_settings.json` 自定义服务器设置:
@@ -48,31 +53,59 @@ MCPHub 是一个统一的 MCPModel Context Protocol模型上下文协议
"SLACK_TEAM_ID": "your-team-id"
}
}
},
"users": [
{
"username": "admin",
"password": "$2b$10$Vt7krIvjNgyN67LXqly0uOcTpN0LI55cYRbcKC71pUDAP0nJ7RPa.",
"isAdmin": true
}
]
}
}
```
> **提示**:默认用户名/密码为 `admin` / `admin123`。密码已通过 bcrypt 安全哈希。生成新密码哈希:
>
> ```bash
> npx bcryptjs your-password
> ```
#### OAuth 配置(可选)
MCPHub 支持通过 OAuth 2.0 访问上游 MCP 服务器。完整说明请参阅[《OAuth 功能指南》](docs/zh/features/oauth.mdx)。实际使用中通常会遇到两类配置:
- **支持动态注册的服务器**(如 Vercel、Linear会公开全部元数据MCPHub 可自动注册并完成授权,仅需声明服务器地址。
- **需要手动配置客户端的服务器**(如 GitHub Copilot需要在提供商后台创建 OAuth 应用,并将获得的 Client ID/Secret 写入 MCPHub。
动态注册示例:
```json
{
"mcpServers": {
"vercel": {
"type": "sse",
"url": "https://mcp.vercel.com"
}
}
}
```
手动注册示例:
```json
{
"mcpServers": {
"github": {
"type": "sse",
"url": "https://api.githubcopilot.com/mcp/",
"oauth": {
"clientId": "${GITHUB_OAUTH_APP_ID}",
"clientSecret": "${GITHUB_OAUTH_APP_SECRET}"
}
}
}
}
```
对于需要手动注册的提供商,请先在上游控制台创建 OAuth 应用,将回调地址设置为 `http://localhost:3000/oauth/callback`(或你的部署域名),然后在控制台或配置文件中填写凭据。
### Docker 部署
**推荐**:挂载自定义配置:
```bash
docker run -p 3000:3000 -v $(pwd)/mcp_settings.json:/app/mcp_settings.json samanhappy/mcphub
docker run -p 3000:3000 -v ./mcp_settings.json:/app/mcp_settings.json -v ./data:/app/data samanhappy/mcphub
```
或使用默认配置运行:
```bash
docker run -p 3000:3000 samanhappy/mcphub
```
@@ -80,34 +113,136 @@ docker run -p 3000:3000 samanhappy/mcphub
### 访问控制台
打开 `http://localhost:3000`,使用您的账号登录。
> **提示**:默认用户名/密码为 `admin` / `admin123`。
**控制台功能**
- 实时监控所有 MCP 服务器状态
- 启用/禁用或重新配置服务器
- 分组管理,组织服务器访问
- 用户管理,设定权限
### SSE 端点集成
### 支持流式的 HTTP 端点
> 截至目前,各家 AI 客户端对流式的 HTTP 端点支持不一,如果遇到问题,可以使用 SSE 端点或者等待更新。
通过以下地址连接 AI 客户端(如 Claude Desktop、Cursor、DeepChat 等):
```
http://localhost:3000/mcp
```
这个端点为所有 MCP 服务器提供统一的流式 HTTP 接口。它允许您:
- 向任何配置的 MCP 服务器发送请求
- 实时接收响应
- 轻松与各种 AI 客户端和工具集成
- 对所有服务器使用相同的端点,简化集成过程
**智能路由(实验性功能)**
智能路由是 MCPHub 的智能工具发现系统,使用向量语义搜索自动为任何给定任务找到最相关的工具。
```
# 在所有服务器中搜索
http://localhost:3000/mcp/$smart
# 在特定分组中搜索
http://localhost:3000/mcp/$smart/{group}
```
**工作原理:**
1. **工具索引**:所有 MCP 工具自动转换为向量嵌入并存储在 PostgreSQL 与 pgvector 中
2. **语义搜索**:用户查询转换为向量并使用余弦相似度与工具嵌入匹配
3. **智能筛选**:动态阈值确保相关结果且无噪声
4. **精确执行**:找到的工具可以直接执行并进行适当的参数验证
5. **分组限定**:可选择将搜索限制在特定分组的服务器内以获得更精确的结果
**设置要求:**
![智能路由](assets/smart-routing.zh.png)
为了启用智能路由,您需要:
- 支持 pgvector 扩展的 PostgreSQL
- OpenAI API 密钥(或兼容的嵌入服务)
- 在 MCPHub 设置中启用智能路由
**分组限定的智能路由**
您可以将智能路由与分组筛选结合使用,仅在特定服务器分组内搜索:
```
# 仅在生产服务器中搜索
http://localhost:3000/mcp/$smart/production
# 仅在开发服务器中搜索
http://localhost:3000/mcp/$smart/development
```
这样可以实现:
- **精准发现**:仅从相关服务器查找工具
- **环境隔离**:按环境(开发、测试、生产)分离工具发现
- **基于团队的访问**:将工具搜索限制在特定团队的服务器分组
**基于分组的 HTTP 端点(推荐)**
![分组](assets/group.zh.png)
要针对特定服务器分组进行访问,请使用基于分组的 HTTP 端点:
```
http://localhost:3000/mcp/{group}
```
其中 `{group}` 是您在控制面板中创建的分组 ID 或名称。这样做可以:
- 连接到按用例组织的特定 MCP 服务器子集
- 隔离不同的 AI 工具,使其只能访问相关服务器
- 为不同环境或团队实现更精细的访问控制
- 通过分组名称轻松识别和管理服务器
- 允许不同的 AI 客户端使用相同的端点,简化集成过程
**针对特定服务器的 HTTP 端点**
要针对特定服务器进行访问,请使用以下格式:
```
http://localhost:3000/mcp/{server}
```
其中 `{server}` 是您要连接的服务器名称。这样做可以直接访问特定的 MCP 服务器。
> **提示**:如果服务器名称和分组名称相同,则分组名称优先。
### SSE 端点集成 (未来可能废弃)
通过以下地址连接 AI 客户端(如 Claude Desktop、Cursor、DeepChat 等):
通过以下地址连接 AI 客户端(如 Claude Desktop、Cursor、Cherry Studio 等):
```
http://localhost:3000/sse
```
**基于分组的 SSE 端点(推荐)**
要启用智能路由,请使用:
![分组](assets/group.zh.png)
```
# 在所有服务器中搜索
http://localhost:3000/sse/$smart
# 在特定分组中搜索
http://localhost:3000/sse/$smart/{group}
```
要针对特定服务器分组进行访问,请使用基于分组的 SSE 端点:
```
http://localhost:3000/sse/{groupId}
http://localhost:3000/sse/{group}
```
其中 `{groupId}` 是您在控制面板中创建的分组 ID。这样做可以
- 连接到按用例组织的特定 MCP 服务器子集
- 隔离不同的 AI 工具,使其只能访问相关服务器
- 为不同环境或团队实现更精细的访问控制
要针对特定服务器进行访问,请使用以下格式
```
http://localhost:3000/sse/{server}
```
## 🧑‍💻 本地开发
@@ -120,6 +255,18 @@ pnpm dev
此命令将在开发模式下启动前后端,并启用热重载。
> 针对 Windows 用户,可能需要分别启动后端服务器和前端:`pnpm backend:dev``pnpm frontend:dev`。
## 🛠️ 常见问题
### 使用 nginx 反向代理
如果您在使用 nginx 反向代理 MCPHub请确保在 nginx 配置中添加以下内容:
```nginx
proxy_buffering off
```
## 🔍 技术栈
- **后端**Node.js、Express、TypeScript
@@ -140,6 +287,18 @@ pnpm dev
<img src="assets/wexin.png" width="350">
如果觉得项目有帮助,不妨请我喝杯咖啡 ☕️
<img src="assets/reward.png" width="350">
## 致谢
感谢以下人员的赞赏:小白、琛。你们的支持是我继续前进的动力!
## 🌟 Star 历史趋势
[![Star History Chart](https://api.star-history.com/svg?repos=samanhappy/mcphub&type=Date)](https://www.star-history.com/#samanhappy/mcphub&Date)
## 📄 许可证
本项目采用 [Apache 2.0 许可证](LICENSE)。

254
SECURITY_FIX_SUMMARY.md Normal file
View File

@@ -0,0 +1,254 @@
# Authentication Bypass Vulnerability Fix
## Summary
This document describes the authentication bypass vulnerability discovered in MCPHub and the fixes implemented to address it.
## Vulnerability Description
**Severity**: Critical
**Impact**: Remote attackers could impersonate any user and access MCP tools without authentication
**Affected Versions**: All versions prior to this fix
### Attack Scenarios
1. **User Impersonation via URL Manipulation**
- Attacker could access `/admin/mcp/alice-private` without credentials
- System would create session with admin privileges
- Attacker could call MCP tools with admin access
2. **Bearer Auth Bypass**
- Even with `enableBearerAuth: true` in configuration
- Bearer token validation was never performed
- Any client could bypass authentication
3. **Credentials Not Required**
- No JWT, OAuth, or bearer tokens needed
- Simply placing a username in URL granted access
- All MCP servers accessible to attacker
## Root Causes
### 1. Unvalidated User Context (`src/middlewares/userContext.ts`)
**Lines 41-96**: `sseUserContextMiddleware` trusted the `/:user/` path segment without validation:
```typescript
// VULNERABLE CODE (before fix):
if (username) {
const user: IUser = {
username, // Trusted from URL!
password: '',
isAdmin: false,
};
userContextService.setCurrentUser(user);
// No authentication check!
}
```
**Impact**: Attackers could inject any username via URL and gain that user's privileges.
### 2. Bearer Auth Configuration Bypass (`src/services/sseService.ts`)
**Lines 33-66**: `validateBearerAuth` used `loadSettings()` which filtered out configuration:
```typescript
// VULNERABLE CODE (before fix):
const settings = loadSettings(); // Uses DataServicex.filterSettings()
const routingConfig = settings.systemConfig?.routing || {
enableBearerAuth: false, // Always defaults to false!
};
```
**Chain of failures**:
1. `loadSettings()` calls `DataServicex.filterSettings()`
2. For unauthenticated users (no context), `filterSettings()` removes `systemConfig`
3. `routingConfig` falls back to defaults with `enableBearerAuth: false`
4. Bearer auth never enforced
### 3. Authentication Middleware Scope
**File**: `src/server.ts`
**Issue**: Auth middleware only mounted under `/api/**` routes
**Impact**: MCP/SSE endpoints (`/mcp`, `/sse`, `/:user/mcp`, `/:user/sse`) were unprotected
## Fixes Implemented
### Fix 1: Validate User-Scoped Route Authentication
**File**: `src/middlewares/userContext.ts`
**Lines**: 41-96 (sseUserContextMiddleware)
```typescript
// FIXED CODE:
if (username) {
// SECURITY: Require authentication for user-scoped routes
const bearerUser = resolveOAuthUserFromAuthHeader(rawAuthHeader);
if (bearerUser) {
// Verify authenticated user matches requested username
if (bearerUser.username !== username) {
res.status(403).json({
error: 'forbidden',
error_description: `Authenticated user '${bearerUser.username}' cannot access resources for user '${username}'`,
});
return;
}
userContextService.setCurrentUser(bearerUser);
} else {
// No valid authentication
res.status(401).json({
error: 'unauthorized',
error_description: 'Authentication required for user-scoped MCP endpoints',
});
return;
}
}
```
**Security improvements**:
- ✅ Requires valid OAuth/bearer token for user-scoped routes
- ✅ Validates authenticated user matches requested username
- ✅ Returns 401 if no authentication provided
- ✅ Returns 403 if user mismatch
- ✅ Prevents URL-based user impersonation
### Fix 2: Use Unfiltered Settings for Bearer Auth
**File**: `src/services/sseService.ts`
**Lines**: 33-66 (validateBearerAuth)
```typescript
// FIXED CODE:
const validateBearerAuth = (req: Request): BearerAuthResult => {
// SECURITY FIX: Use loadOriginalSettings() to bypass user filtering
const settings = loadOriginalSettings(); // Was: loadSettings()
// Handle undefined (e.g., in tests)
if (!settings) {
return { valid: true };
}
const routingConfig = settings.systemConfig?.routing || {
enableGlobalRoute: true,
enableGroupNameRoute: true,
enableBearerAuth: false,
bearerAuthKey: '',
};
if (routingConfig.enableBearerAuth) {
// Bearer auth validation now works correctly
// ...
}
return { valid: true };
};
```
**Security improvements**:
- ✅ Reads actual `systemConfig` from settings file
- ✅ Not affected by user-context filtering
- ✅ Bearer auth correctly enforced when configured
- ✅ Configuration cannot be bypassed
## Testing
### Security Tests Added
**File**: `tests/security/auth-bypass.test.ts` (8 tests)
1. ✅ Rejects unauthenticated requests to user-scoped routes
2. ✅ Rejects requests when authenticated user doesn't match URL username
3. ✅ Allows authenticated users to access their own resources
4. ✅ Allows admin users with matching username
5. ✅ Allows global routes without authentication
6. ✅ Sets user context for global routes with valid OAuth token
7. ✅ Prevents impersonation by URL manipulation
8. ✅ Prevents impersonation with valid token for different user
**File**: `tests/security/bearer-auth-bypass.test.ts` (2 tests)
1. ✅ Documents vulnerability and fix details
2. ✅ Explains DataServicex.filterSettings behavior
**All 10 security tests pass successfully.**
### Test Execution
```bash
$ pnpm test tests/security/
PASS tests/security/auth-bypass.test.ts
PASS tests/security/bearer-auth-bypass.test.ts
Test Suites: 2 passed, 2 total
Tests: 10 passed, 10 total
```
## Verification
### Before Fix
```bash
# Attacker could impersonate admin without credentials:
POST http://localhost:3000/admin/mcp/secret-group
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {...}
}
# Response: 200 OK with mcp-session-id
# Attacker has admin access!
```
### After Fix
```bash
# Same request now requires authentication:
POST http://localhost:3000/admin/mcp/secret-group
# Response: 401 Unauthorized
{
"error": "unauthorized",
"error_description": "Authentication required for user-scoped MCP endpoints"
}
# With token for wrong user:
POST http://localhost:3000/admin/mcp/secret-group
Authorization: Bearer bob-token
# Response: 403 Forbidden
{
"error": "forbidden",
"error_description": "Authenticated user 'bob' cannot access resources for user 'admin'"
}
```
## Security Recommendations
1. **Update immediately**: This is a critical vulnerability
2. **Review access logs**: Check for unauthorized access attempts
3. **Rotate credentials**: Change bearer auth keys if compromised
4. **Network security**: Use firewall rules to restrict MCP port access
5. **Enable bearer auth**: Set `enableBearerAuth: true` in mcp_settings.json
6. **Use OAuth**: Configure OAuth for additional security layer
## Configuration Example
**mcp_settings.json**:
```json
{
"systemConfig": {
"routing": {
"enableGlobalRoute": false,
"enableGroupNameRoute": true,
"enableBearerAuth": true,
"bearerAuthKey": "your-secure-random-key-here"
}
}
}
```
## Credits
- **Vulnerability discovered by**: Security researcher (as per report)
- **Fixes implemented by**: GitHub Copilot
- **Repository**: github.com/samanhappy/mcphub

187
SECURITY_SUMMARY.md Normal file
View File

@@ -0,0 +1,187 @@
# Security Summary - OAuth Authorization Server Implementation
## Overview
This document summarizes the security analysis and measures taken for the OAuth 2.0 authorization server implementation in MCPHub.
## Vulnerability Scan Results
### Dependency Vulnerabilities
**PASSED**: No vulnerabilities found in dependencies
- `@node-oauth/oauth2-server@5.2.1` - Clean scan, no known vulnerabilities
- All other dependencies scanned and verified secure
### Code Security Analysis (CodeQL)
⚠️ **ADVISORY**: 12 alerts found regarding missing rate limiting on authentication endpoints
**Details:**
- **Issue**: Authorization routes do not have rate limiting middleware
- **Impact**: Potential brute force attacks on authentication endpoints
- **Severity**: Medium
- **Status**: Documented, not critical
**Affected Endpoints:**
- `/oauth/authorize` (GET/POST)
- `/oauth/token` (POST)
- `/api/oauth/clients/*` (various methods)
**Mitigation:**
1. All endpoints require proper authentication
2. Authorization codes expire after 5 minutes by default
3. Access tokens expire after 1 hour by default
4. Failed authentication attempts are logged
5. Documentation includes rate limiting recommendations for production
**Recommended Actions for Production:**
- Implement `express-rate-limit` middleware on OAuth endpoints
- Consider using reverse proxy rate limiting (nginx, Cloudflare)
- Monitor for suspicious authentication patterns
- Set up alerting for repeated failed attempts
## Security Features Implemented
### Authentication & Authorization
**OAuth 2.0 Compliance**: Fully compliant with RFC 6749
**PKCE Support**: RFC 7636 implementation for public clients
**Token-based Authentication**: Access tokens and refresh tokens
**JWT Integration**: Backward compatible with existing JWT auth
**User Permissions**: Proper admin status lookup for OAuth users
### Input Validation
**Query Parameter Validation**: All OAuth parameters validated with regex patterns
**Client ID Validation**: Alphanumeric with hyphens/underscores only
**Redirect URI Validation**: Strict matching against registered URIs
**Scope Validation**: Only allowed scopes can be requested
**State Parameter**: CSRF protection via state validation
### Output Security
**XSS Protection**: All user input HTML-escaped in authorization page
**HTML Escaping**: Custom escapeHtml function for template rendering
**Safe Token Handling**: Tokens never exposed in URLs or logs
### Token Security
**Secure Token Generation**: Cryptographically random tokens (32 bytes)
**Token Expiration**: Configurable lifetimes for all token types
**Token Revocation**: Support for revoking access and refresh tokens
**Automatic Cleanup**: Expired tokens automatically removed from memory
### Transport Security
**HTTPS Ready**: Designed for HTTPS in production
**No Tokens in URL**: Access tokens never passed in query parameters
**Secure Headers**: Proper Content-Type and security headers
### Client Security
**Client Secret Support**: Optional for confidential clients
**Public Client Support**: PKCE for clients without secrets
**Redirect URI Whitelist**: Strict validation of redirect destinations
**Client Registration**: Secure client management API
### Code Quality
**TypeScript Strict Mode**: Full type safety
**ESLint Clean**: No linting errors
**Test Coverage**: 180 tests passing, including 11 OAuth-specific tests
**Async Safety**: Proper async/await usage throughout
**Resource Cleanup**: Graceful shutdown support with interval cleanup
## Security Best Practices Followed
1. **Defense in Depth**: Multiple layers of security (auth, validation, escaping)
2. **Principle of Least Privilege**: Scopes limit what clients can access
3. **Fail Securely**: Invalid requests rejected with appropriate errors
4. **Security by Default**: Secure settings out of the box
5. **Standard Compliance**: Following OAuth 2.0 and PKCE RFCs
6. **Code Reviews**: All changes reviewed for security implications
7. **Documentation**: Comprehensive security guidance provided
## Known Limitations
### In-Memory Token Storage
**Issue**: Tokens stored in memory, not persisted to database
**Impact**: Tokens lost on server restart
**Mitigation**: Refresh tokens allow users to re-authenticate
**Future**: Consider database storage for production deployments
### Rate Limiting
**Issue**: No built-in rate limiting on OAuth endpoints
**Impact**: Potential brute force attacks
**Mitigation**:
- Short-lived authorization codes (5 min default)
- Authentication required for authorization endpoint
- Documented recommendations for production
**Future**: Consider adding rate limiting middleware
### Token Introspection
**Issue**: No token introspection endpoint (RFC 7662)
**Impact**: Limited third-party token validation
**Mitigation**: Clients can use userinfo endpoint
**Future**: Consider implementing RFC 7662 if needed
## Production Deployment Recommendations
### Critical
1. ✅ Use HTTPS in production (SSL/TLS certificates)
2. ✅ Change default admin password immediately
3. ✅ Use strong client secrets for confidential clients
4. ⚠️ Implement rate limiting (express-rate-limit or reverse proxy)
5. ✅ Enable proper logging and monitoring
### Recommended
6. Consider using a database for token storage
7. Set up automated security scanning in CI/CD
8. Use a reverse proxy (nginx) with security headers
9. Implement IP whitelisting for admin endpoints
10. Regular security audits and dependency updates
### Optional
11. Implement token introspection endpoint
12. Add support for JWT-based access tokens
13. Integrate with external OAuth providers
14. Implement advanced scope management
15. Add OAuth client approval workflow
## Compliance & Standards
**OAuth 2.0 (RFC 6749)**: Full authorization code grant implementation
**PKCE (RFC 7636)**: Code challenge and verifier support
**OAuth Server Metadata (RFC 8414)**: Discovery endpoint available
**OpenID Connect Compatible**: Basic userinfo endpoint
## Vulnerability Disclosure
If you discover a security vulnerability in MCPHub's OAuth implementation, please:
1. **Do Not** create a public GitHub issue
2. Email the maintainers privately
3. Provide detailed reproduction steps
4. Allow time for a fix before public disclosure
## Security Update Policy
- **Critical vulnerabilities**: Patched within 24-48 hours
- **High severity**: Patched within 1 week
- **Medium severity**: Patched in next minor release
- **Low severity**: Patched in next patch release
## Conclusion
The OAuth 2.0 authorization server implementation in MCPHub follows security best practices and is production-ready with the noted limitations. The main advisory regarding rate limiting should be addressed in production deployments through application-level or reverse proxy rate limiting.
**Overall Security Assessment**: ✅ **SECURE** with production hardening recommendations
**Last Updated**: 2025-11-02
**Next Review**: Recommended quarterly or after major changes

BIN
articals/assets/sr-conf.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
articals/assets/sr-dc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
articals/assets/sr-time.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
articals/assets/sr-web.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -48,11 +48,11 @@ MCPHub 已内置多个常用 MCP 服务如高德地图、GitHub、Slack、Fet
![配置高德地图](../assets/amap-edit.png)
点击保存后MCP Hub 将自动重启高德地图的 MCP 服务,使新配置生效。
点击保存后MCPHub 将自动重启高德地图的 MCP 服务,使新配置生效。
### 配置 MCP Hub SSE
### 配置 MCPHub SSE
MCP Hub 提供了单一聚合的 MCP Server SSE 端点:`http://localhost:3000/sse`,可在任意支持 MCP 的客户端中配置使用。这里我们选择开源的 Cherry Studio 进行演示。
MCPHub 提供了单一聚合的 MCP Server SSE 端点:`http://localhost:3000/sse`,可在任意支持 MCP 的客户端中配置使用。这里我们选择开源的 Cherry Studio 进行演示。
![配置 Cherry Studio](../assets/cherry-mcp.png)

177
articals/smart-routing.md Normal file
View File

@@ -0,0 +1,177 @@
# 无限工具智能路由MCPHub 引领 AI 工具使用新范式
## 概述
在现代 AI 应用中,随着 MCP 服务器数量的快速增长和工具种类的不断丰富,如何从数百个可用工具中快速定位最适合当前任务的工具,成为开发者和 AI 助手面临的一项重要挑战。
传统做法要么将所有工具暴露给 AI 助手处理,导致 token 消耗巨大、响应延迟严重;要么依赖开发者手动分组配置,灵活性和智能性不足。
MCPHub 推出的智能路由功能,基于向量语义搜索技术,实现了自然语言驱动的工具发现与精准推荐。它让 AI 助手能够像人类专家一样,根据任务描述自动选择最优工具组合,大幅提升了系统效率和用户体验。
## 什么是智能路由
### 技术原理
智能路由是 MCPHub 的核心功能之一。它将每个 MCP 工具的名称和描述嵌入为高维语义向量。当用户发起自然语言任务请求时,系统会将该请求也转换为向量,通过计算相似度,快速返回最相关的工具列表。
这一过程摒弃了传统的关键词匹配,具备更强的语义理解能力,能够处理自然语言的模糊性和多样性。
### 核心组件
- **向量嵌入引擎**:支持如 `text-embedding-3-small``bge-m3` 等主流模型,将文本描述转为语义向量。
- **PostgreSQL + pgvector**:使用开源向量数据库方案,支持高效的向量索引和搜索。
- **两步工作流分离**
- `search_tools`:负责语义工具发现
- `call_tool`:执行实际工具调用逻辑
## 为什么需要智能路由
### 1. 减少认知负荷
- 当工具数量超过 100 个AI 模型难以处理所有工具上下文。
- 智能路由通过语义压缩,将候选工具缩小至 510 个,提高决策效率。
### 2. 显著降低 token 消耗
- 传统做法传入全量工具描述,可能消耗上千 token。
- 使用智能路由,通常可将 token 使用降低 7090%。
### 3. 提升调用准确率
- 理解任务语义:如“图片增强”→选择图像处理工具,而不是依赖命名关键词。
- 上下文感知:考虑输入/输出格式和工具组合能力,匹配更合理的执行链路。
## 智能路由配置指南
### 1. 启动支持 `pgvector` 的 PostgreSQL 数据库
```bash
docker run --name mcphub-postgres \
-e POSTGRES_DB=mcphub \
-e POSTGRES_USER=mcphub \
-e POSTGRES_PASSWORD=your_password \
-p 5432:5432 \
-d pgvector/pgvector:pg17
```
如已部署 PostgreSQL可直接创建数据库并启用 `pgvector` 扩展:
```sql
CREATE DATABASE mcphub;
CREATE EXTENSION vector;
```
### 2. 获取 embedding 模型的 API Key
前往 OpenAI 或其他提供商获取嵌入模型的 API Key。国内用户推荐使用硅基流动 `bge-m3` 免费模型,没有注册过的用户可以使用我的邀请链接:[https://cloud.siliconflow.cn/i/TQhVYBvA](https://cloud.siliconflow.cn/i/TQhVYBvA)。
### 3. 控制台配置
![配置](./assets/sr-conf.png)
在 MCPHub 控制台中,进入「智能路由」配置页面,填写以下信息:
- **数据库 URL**`postgresql://mcphub:your_password@localhost:5432/mcphub`
- **OpenAI API Key** :填写你获取的嵌入模型 API Key
- **OpenAI 基础 URL**`https://api.siliconflow.cn/v1`
- **嵌入模型**:推荐使用 `BAAI/bge-m3`
开启「启用智能路由」后系统会自动:
- 对所有工具生成向量嵌入
- 构建向量索引
- 自动监听新增工具,更新索引
## 工具定义
### search_tools - 工具搜索
```ts
{
"name": "search_tools",
"arguments": {
"query": "help me resize and convert images",
"limit": 10
}
}
```
### call_tool - 工具执行
```ts
{
"name": "call_tool",
"arguments": {
"toolName": "image_resizer",
"arguments": {
"input_path": "/path/to/image.png",
"width": 800,
"height": 600
}
}
}
```
## 演示
下面我将通过几个示例来展示如何使用智能路由。
首先,我们需要在 mcphub 添加几个不同类型的 MCP 服务器:`amap``time-map``fetch`
![添加服务器](./assets/sr-servers.png)
然后我们需要选择一个支持 MCP 的客户端,这里选择国产的 DeepChat聊天模型选择 `Qwen3-14B`
接着,在 DeepChat 中添加 mcphub 的智能路由端点:
![添加智能路由](./assets/sr-dc.png)
添加成功后,就可以在工具中看到 `search_tools``call_tool` 两个工具了:
![工具列表](./assets/sr-tools.png)
### 示例 1地图导航
输入:从北京如何导航到上海。
结果:
![地图导航](./assets/sr-map-result.png)
可以看到DeepChat 先调用了 `search_tools` 工具:
![搜索工具](./assets/sr-map-search.png)
然后再调用 `call_tool` 查询具体的导航信息:
![调用工具](./assets/sr-map-call.png)
### 示例 2查询时间
输入:使用工具查询美国现在的时间是几点
结果:
![查询时间](./assets/sr-time.png)
需要说明的是,由于不同的模型对工具调用的支持程度不同,可能会出现一些差异。比如在这个例子中,为了提高准确性,我在输入中明确提到了“使用工具”。
### 示例 3查看网页
输入:打开 baidu.com 看看有什么
结果:
![查看网页](./assets/sr-web.png)
可以看到DeepChat 成功调用了工具,不过由于百度的 robots.txt 限制,无法获取到具体内容。
## 结语
借助 MCPHub 的智能路由功能AI 助手能够更高效地处理复杂任务,显著减少不必要的 token 消耗,同时提升工具调用的准确性与灵活性。作为面向未来的 AI 工具发现与调用基础设施,智能路由不仅使 AI 更聪明地选择和组合工具,还为多 Agent 协同提供了清晰、可控且可扩展的底层能力支撑。
> MCPHub 只是我一时兴起开发的小项目,没想到收获了这么多关注,非常感谢大家的支持!目前 MCPHub 还有不少地方需要优化和完善,我也专门建了个交流群,感兴趣的可以添加下面的微信。
![微信](../assets/wexin.png)
> 同时,欢迎大家一起参与建设!项目地址为:[https://github.com/samanhappy/mcphub](https://github.com/samanhappy/mcphub)。

BIN
assets/reward.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
assets/smart-routing.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
assets/smart-routing.zh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

98
bin/cli.js Executable file
View File

@@ -0,0 +1,98 @@
#!/usr/bin/env node
import path from 'path';
import { fileURLToPath, pathToFileURL } from 'url';
import fs from 'fs';
// Enable debug logging if needed
// process.env.DEBUG = 'true';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Start with more debug information
console.log('📋 MCPHub CLI');
console.log(`📁 CLI script location: ${__dirname}`);
// The npm package directory structure when installed is:
// node_modules/@samanhappy/mcphub/
// - dist/
// - bin/
// - frontend/dist/
// Get the package root - this is where package.json is located
function findPackageRoot() {
const isDebug = process.env.DEBUG === 'true';
// Possible locations for package.json
const possibleRoots = [
// Standard npm package location
path.resolve(__dirname, '..'),
// When installed via npx
path.resolve(__dirname, '..', '..', '..')
];
// Special handling for npx
if (process.argv[1] && process.argv[1].includes('_npx')) {
const npxDir = path.dirname(process.argv[1]);
possibleRoots.unshift(path.resolve(npxDir, '..'));
}
if (isDebug) {
console.log('DEBUG: Checking for package.json in:', possibleRoots);
}
for (const root of possibleRoots) {
const packageJsonPath = path.join(root, 'package.json');
if (fs.existsSync(packageJsonPath)) {
try {
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
if (pkg.name === 'mcphub' || pkg.name === '@samanhappy/mcphub') {
if (isDebug) {
console.log(`DEBUG: Found package.json at ${packageJsonPath}`);
}
return root;
}
} catch (e) {
// Continue to the next potential root
}
}
}
console.log('⚠️ Could not find package.json, using default path');
return path.resolve(__dirname, '..');
}
// Locate and check the frontend distribution
function checkFrontend(packageRoot) {
const isDebug = process.env.DEBUG === 'true';
const frontendDistPath = path.join(packageRoot, 'frontend', 'dist');
if (isDebug) {
console.log(`DEBUG: Checking frontend at: ${frontendDistPath}`);
}
if (fs.existsSync(frontendDistPath) && fs.existsSync(path.join(frontendDistPath, 'index.html'))) {
console.log('✅ Frontend distribution found');
return true;
} else {
console.log('⚠️ Frontend distribution not found at', frontendDistPath);
return false;
}
}
const projectRoot = findPackageRoot();
console.log(`📦 Using package root: ${projectRoot}`);
// Check if frontend exists
checkFrontend(projectRoot);
// Start the server
console.log('🚀 Starting MCPHub server...');
const entryPath = path.join(projectRoot, 'dist', 'index.js');
// Convert to file:// URL for cross-platform ESM compatibility (required on Windows)
const entryUrl = pathToFileURL(entryPath).href;
import(entryUrl).catch(err => {
console.error('Failed to start MCPHub:', err);
process.exit(1);
});

32
docs/README.md Normal file
View File

@@ -0,0 +1,32 @@
# Mintlify Starter Kit
Click on `Use this template` to copy the Mintlify starter kit. The starter kit contains examples including
- Guide pages
- Navigation
- Customizations
- API Reference pages
- Use of popular components
### Development
Install the [Mintlify CLI](https://www.npmjs.com/package/mintlify) to preview the documentation changes locally. To install, use the following command
```
npm i -g mintlify
```
Run the following command at the root of your documentation (where docs.json is)
```
mintlify dev
```
### Publishing Changes
Install our Github App to auto propagate changes from your repo to your deployment. Changes will be deployed to production automatically after pushing to the default branch. Find the link to install on your dashboard.
#### Troubleshooting
- Mintlify dev isn't running - Run `mintlify install` it'll re-install dependencies.
- Page loads as a 404 - Make sure you are running in a folder with `docs.json`

147
docs/api-reference/auth.mdx Normal file
View File

@@ -0,0 +1,147 @@
---
title: "Authentication"
description: "Manage users and authentication."
---
import { Card, Cards } from 'mintlify';
<Card
title="POST /api/auth/login"
href="#login"
>
Log in to get a JWT token.
</Card>
<Card
title="POST /api/auth/register"
href="#register"
>
Register a new user.
</Card>
<Card
title="GET /api/auth/user"
href="#get-current-user"
>
Get the currently authenticated user.
</Card>
<Card
title="POST /api/auth/change-password"
href="#change-password"
>
Change the password for the current user.
</Card>
---
### Login
Authenticates a user and returns a JWT token along with user details.
- **Endpoint**: `/api/auth/login`
- **Method**: `POST`
- **Body**:
- `username` (string, required): The user's username.
- `password` (string, required): The user's password.
- **Request Example**:
```json
{
"username": "admin",
"password": "admin123"
}
```
- **Success Response**:
```json
{
"success": true,
"message": "Login successful",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"username": "admin",
"isAdmin": true,
"permissions": { ... }
}
}
```
---
### Register
Registers a new user and returns a JWT token.
- **Endpoint**: `/api/auth/register`
- **Method**: `POST`
- **Body**:
- `username` (string, required): The desired username.
- `password` (string, required): The desired password (must be at least 6 characters).
- `isAdmin` (boolean, optional): Whether the user should have admin privileges.
- **Request Example**:
```json
{
"username": "newuser",
"password": "password123",
"isAdmin": false
}
```
- **Success Response**:
```json
{
"success": true,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"username": "newuser",
"isAdmin": false,
"permissions": { ... }
}
}
```
---
### Get Current User
Retrieves the profile of the currently authenticated user.
- **Endpoint**: `/api/auth/user`
- **Method**: `GET`
- **Authentication**: Bearer Token required.
- **Success Response**:
```json
{
"success": true,
"user": {
"username": "admin",
"isAdmin": true,
"permissions": { ... }
}
}
```
---
### Change Password
Allows the authenticated user to change their password.
- **Endpoint**: `/api/auth/change-password`
- **Method**: `POST`
- **Authentication**: Bearer Token required.
- **Body**:
- `currentPassword` (string, required): The user's current password.
- `newPassword` (string, required): The desired new password (must be at least 6 characters).
- **Request Example**:
```json
{
"currentPassword": "oldpassword",
"newPassword": "newpassword123"
}
```
- **Success Response**:
```json
{
"success": true,
"message": "Password updated successfully"
}
```

View File

@@ -0,0 +1,111 @@
---
title: "Config"
description: "Manage and retrieve system-wide configurations."
---
import { Card, Cards } from 'mintlify';
<Card title="PUT /api/system-config" href="#update-system-config">Update the main system configuration.</Card>
<Card title="GET /api/settings" href="#get-all-settings">Get all system settings, including servers and groups.</Card>
<Card title="GET /config" href="#get-runtime-config">Get public runtime configuration for the frontend.</Card>
<Card title="GET /public-config" href="#get-public-config">Get public configuration to check for auth skip.</Card>
---
### Update System Config
Updates various parts of the system configuration. You only need to provide the keys for the sections you want to update.
- **Endpoint**: `/api/system-config`
- **Method**: `PUT`
- **Body**: A JSON object containing one or more of the following top-level keys: `routing`, `install`, `smartRouting`, `mcpRouter`.
#### Routing Configuration (`routing`)
- `enableGlobalRoute` (boolean): Enable or disable the global `/api/mcp` route.
- `enableGroupNameRoute` (boolean): Enable or disable group-based routing (e.g., `/api/mcp/group/:groupName`).
- `enableBearerAuth` (boolean): Enable bearer token authentication for MCP routes.
- `bearerAuthKey` (string): The secret key to use for bearer authentication.
- `skipAuth` (boolean): If true, skips all authentication, making the instance public.
#### Install Configuration (`install`)
- `pythonIndexUrl` (string): The base URL of the Python Package Index (PyPI) to use for installations.
- `npmRegistry` (string): The URL of the npm registry to use for installations.
- `baseUrl` (string): The public base URL of this MCPHub instance.
#### Smart Routing Configuration (`smartRouting`)
- `enabled` (boolean): Enable or disable the Smart Routing feature.
- `dbUrl` (string): The database connection URL for storing embeddings.
- `openaiApiBaseUrl` (string): The base URL for the OpenAI-compatible API for generating embeddings.
- `openaiApiKey` (string): The API key for the embeddings service.
- `openaiApiEmbeddingModel` (string): The name of the embedding model to use.
#### MCP Router Configuration (`mcpRouter`)
- `apiKey` (string): The API key for the MCP Router service.
- `referer` (string): The referer header to use for MCP Router requests.
- `title` (string): The title to display for this instance on MCP Router.
- `baseUrl` (string): The base URL for the MCP Router API.
- **Request Example**:
```json
{
"routing": {
"skipAuth": true
},
"smartRouting": {
"enabled": true,
"dbUrl": "postgresql://user:pass@host:port/db"
}
}
```
---
### Get All Settings
Retrieves the entire settings object for the instance, including all server configurations, groups, and system settings. This is a comprehensive dump of the `mcp_settings.json` file.
- **Endpoint**: `/api/settings`
- **Method**: `GET`
---
### Get Runtime Config
Retrieves the essential runtime configuration required for the frontend application. This endpoint does not require authentication.
- **Endpoint**: `/config`
- **Method**: `GET`
- **Success Response**:
```json
{
"success": true,
"data": {
"basePath": "",
"version": "1.0.0",
"name": "MCPHub"
}
}
```
---
### Get Public Config
Retrieves public configuration, primarily to check if authentication is skipped. This allows the frontend to adjust its behavior accordingly before a user has logged in. This endpoint does not require authentication.
- **Endpoint**: `/public-config`
- **Method**: `GET`
- **Success Response**:
```json
{
"success": true,
"data": {
"skipAuth": false,
"permissions": {}
}
}
```

View File

@@ -0,0 +1,212 @@
---
title: "Groups"
description: "Manage server groups to organize and route requests."
---
import { Card, Cards } from 'mintlify';
<Card title="GET /api/groups" href="#get-all-groups">Get a list of all groups.</Card>
<Card title="POST /api/groups" href="#create-a-new-group">Create a new group.</Card>
<Card title="GET /api/groups/:id" href="#get-a-group">Get details of a specific group.</Card>
<Card title="PUT /api/groups/:id" href="#update-a-group">Update an existing group.</Card>
<Card title="DELETE /api/groups/:id" href="#delete-a-group">Delete a group.</Card>
<Card title="POST /api/groups/:id/servers" href="#add-server-to-group">Add a server to a group.</Card>
<Card title="DELETE /api/groups/:id/servers/:serverName" href="#remove-server-from-group">Remove a server from a group.</Card>
<Card title="PUT /api/groups/:id/servers/batch" href="#batch-update-group-servers">Batch update servers in a group.</Card>
<Card title="GET /api/groups/:id/server-configs" href="#get-group-server-configs">Get detailed server configurations in a group.</Card>
<Card title="PUT /api/groups/:id/server-configs/:serverName/tools" href="#update-group-server-tools">Update tool selection for a server in a group.</Card>
---
### Get All Groups
Retrieves a list of all server groups.
- **Endpoint**: `/api/groups`
- **Method**: `GET`
- **Success Response**:
```json
{
"success": true,
"data": [
{
"id": "group-1",
"name": "My Group",
"description": "A collection of servers.",
"servers": ["server1", "server2"],
"owner": "admin"
}
]
}
```
---
### Create a New Group
Creates a new server group.
- **Endpoint**: `/api/groups`
- **Method**: `POST`
- **Body**:
- `name` (string, required): The name of the group.
- `description` (string, optional): A description for the group.
- `servers` (array of strings, optional): A list of server names to include in the group.
- **Request Example**:
```json
{
"name": "My New Group",
"description": "A description for the new group",
"servers": ["server1", "server2"]
}
```
---
### Get a Group
Retrieves details for a specific group by its ID or name.
- **Endpoint**: `/api/groups/:id`
- **Method**: `GET`
- **Parameters**:
- `:id` (string, required): The ID or name of the group.
---
### Update a Group
Updates an existing group's name, description, or server list.
- **Endpoint**: `/api/groups/:id`
- **Method**: `PUT`
- **Parameters**:
- `:id` (string, required): The ID or name of the group to update.
- **Body**:
- `name` (string, optional): The new name for the group.
- `description` (string, optional): The new description for the group.
- `servers` (array, optional): The new list of servers for the group. See [Batch Update Group Servers](#batch-update-group-servers) for format.
- **Request Example**:
```json
{
"name": "Updated Group Name",
"description": "Updated description"
}
```
---
### Delete a Group
Deletes a group by its ID or name.
- **Endpoint**: `/api/groups/:id`
- **Method**: `DELETE`
- **Parameters**:
- `:id` (string, required): The ID or name of the group to delete.
---
### Add Server to Group
Adds a single server to a group.
- **Endpoint**: `/api/groups/:id/servers`
- **Method**: `POST`
- **Parameters**:
- `:id` (string, required): The ID or name of the group.
- **Body**:
- `serverName` (string, required): The name of the server to add.
- **Request Example**:
```json
{
"serverName": "my-server"
}
```
---
### Remove Server from Group
Removes a single server from a group.
- **Endpoint**: `/api/groups/:id/servers/:serverName`
- **Method**: `DELETE`
- **Parameters**:
- `:id` (string, required): The ID or name of the group.
- `:serverName` (string, required): The name of the server to remove.
---
### Batch Update Group Servers
Replaces all servers in a group with a new list. The list can be simple strings or detailed configuration objects.
- **Endpoint**: `/api/groups/:id/servers/batch`
- **Method**: `PUT`
- **Parameters**:
- `:id` (string, required): The ID or name of the group.
- **Body**:
- `servers` (array, required): An array of server names (strings) or server configuration objects.
- **Request Example (Simple)**:
```json
{
"servers": ["server1", "server2"]
}
```
- **Request Example (Detailed)**:
```json
{
"servers": [
{ "name": "server1", "tools": "all" },
{ "name": "server2", "tools": ["toolA", "toolB"] }
]
}
```
---
### Get Group Server Configs
Retrieves the detailed configuration for all servers within a group, including which tools are enabled.
- **Endpoint**: `/api/groups/:id/server-configs`
- **Method**: `GET`
- **Parameters**:
- `:id` (string, required): The ID or name of the group.
- **Success Response**:
```json
{
"success": true,
"data": [
{
"name": "server1",
"tools": "all"
},
{
"name": "server2",
"tools": ["toolA", "toolB"]
}
]
}
```
---
### Update Group Server Tools
Updates the tool selection for a specific server within a group.
- **Endpoint**: `/api/groups/:id/server-configs/:serverName/tools`
- **Method**: `PUT`
- **Parameters**:
- `:id` (string, required): The ID or name of the group.
- `:serverName` (string, required): The name of the server to update.
- **Body**:
- `tools` (string or array of strings, required): Either the string `"all"` to enable all tools, or an array of tool names to enable specifically.
- **Request Example**:
```json
{
"tools": ["toolA", "toolC"]
}
```

View File

@@ -0,0 +1,13 @@
---
title: "Introduction"
description: "Welcome to the MCPHub API documentation."
---
The MCPHub API provides a comprehensive set of endpoints to manage your MCP servers, groups, users, and more. The API is divided into two main categories:
- **MCP Endpoints**: These are the primary endpoints for interacting with your MCP servers. They provide a unified interface for sending requests to your servers and receiving responses in real-time.
- **Management API**: These endpoints are used for managing the MCPHub instance itself. This includes managing servers, groups, users, and system settings.
All API endpoints are available under the `/api` path. For example, the endpoint to get all servers is `/api/servers`.
Authentication is required for most Management API endpoints. See the [Authentication](/api-reference/auth) section for more details.

View File

@@ -0,0 +1,81 @@
---
title: "Logs"
description: "Access and manage server logs."
---
import { Card, Cards } from 'mintlify';
<Card
title="GET /api/logs"
href="#get-all-logs"
>
Get all logs.
</Card>
<Card
title="DELETE /api/logs"
href="#clear-logs"
>
Clear all logs.
</Card>
<Card
title="GET /api/logs/stream"
href="#stream-logs"
>
Stream logs in real-time.
</Card>
---
### Get All Logs
Retrieves all stored logs.
- **Endpoint**: `/api/logs`
- **Method**: `GET`
- **Success Response**:
```json
{
"success": true,
"data": [
{
"timestamp": "2023-10-27T10:00:00.000Z",
"level": "info",
"message": "Server started successfully.",
"service": "system"
}
]
}
```
---
### Clear Logs
Deletes all stored logs.
- **Endpoint**: `/api/logs`
- **Method**: `DELETE`
- **Success Response**:
```json
{
"success": true,
"message": "Logs cleared successfully"
}
```
---
### Stream Logs
Streams logs in real-time using Server-Sent Events (SSE). The connection will remain open, and new log entries will be sent as they occur.
- **Endpoint**: `/api/logs/stream`
- **Method**: `GET`
- **Response Format**: The stream sends events with a `data` field containing a JSON object. The first event has `type: 'initial'` and contains all historical logs. Subsequent events have `type: 'log'` and contain a single new log entry.
- **Example Event**:
```
data: {"type":"log","log":{"timestamp":"2023-10-27T10:00:05.000Z","level":"debug","message":"Processing request for /api/some-endpoint","service":"mcp-server"}}
```

View File

@@ -0,0 +1,33 @@
---
title: "MCP HTTP Endpoints"
description: "Connect to your MCP servers using the unified HTTP endpoint."
---
MCPHub provides a unified streamable HTTP interface for all your MCP servers. This allows you to send requests to any configured MCP server and receive responses in real-time.
### Unified Endpoint
This endpoint provides access to all enabled MCP servers.
- **Endpoint**: `http://localhost:3000/mcp`
- **Method**: `POST`
### Group-Specific Endpoint
For targeted access to specific server groups, use the group-based HTTP endpoint.
- **Endpoint**: `http://localhost:3000/mcp/{group}`
- **Method**: `POST`
- **Parameters**:
- `{group}`: The ID or name of the group.
### Server-Specific Endpoint
For direct access to individual servers, use the server-specific HTTP endpoint.
- **Endpoint**: `http://localhost:3000/mcp/{server}`
- **Method**: `POST`
- **Parameters**:
- `{server}`: The name of the server.
> **Note**: If a server name and group name are the same, the group will take precedence.

View File

@@ -0,0 +1,25 @@
---
title: "MCP SSE Endpoints (Deprecated)"
description: "Connect to your MCP servers using the SSE endpoint."
---
The SSE endpoint is deprecated and will be removed in a future version. Please use the [MCP HTTP Endpoints](/api-reference/mcp-http) instead.
### Unified Endpoint
- **Endpoint**: `http://localhost:3000/sse`
- **Method**: `GET`
### Group-Specific Endpoint
- **Endpoint**: `http://localhost:3000/sse/{group}`
- **Method**: `GET`
- **Parameters**:
- `{group}`: The ID or name of the group.
### Server-Specific Endpoint
- **Endpoint**: `http://localhost:3000/sse/{server}`
- **Method**: `GET`
- **Parameters**:
- `{server}`: The name of the server.

View File

@@ -0,0 +1,217 @@
{
"openapi": "3.1.0",
"info": {
"title": "OpenAPI Plant Store",
"description": "A sample API that uses a plant store as an example to demonstrate features in the OpenAPI specification",
"license": {
"name": "MIT"
},
"version": "1.0.0"
},
"servers": [
{
"url": "http://sandbox.mintlify.com"
}
],
"security": [
{
"bearerAuth": []
}
],
"paths": {
"/plants": {
"get": {
"description": "Returns all plants from the system that the user has access to",
"parameters": [
{
"name": "limit",
"in": "query",
"description": "The maximum number of results to return",
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "Plant response",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Plant"
}
}
}
}
},
"400": {
"description": "Unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"description": "Creates a new plant in the store",
"requestBody": {
"description": "Plant to add to the store",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/NewPlant"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "plant response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Plant"
}
}
}
},
"400": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/plants/{id}": {
"delete": {
"description": "Deletes a single plant based on the ID supplied",
"parameters": [
{
"name": "id",
"in": "path",
"description": "ID of plant to delete",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"responses": {
"204": {
"description": "Plant deleted",
"content": {}
},
"400": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
}
},
"webhooks": {
"/plant/webhook": {
"post": {
"description": "Information about a new plant added to the store",
"requestBody": {
"description": "Plant added to the store",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/NewPlant"
}
}
}
},
"responses": {
"200": {
"description": "Return a 200 status to indicate that the data was received successfully"
}
}
}
}
},
"components": {
"schemas": {
"Plant": {
"required": [
"name"
],
"type": "object",
"properties": {
"name": {
"description": "The name of the plant",
"type": "string"
},
"tag": {
"description": "Tag to specify the type",
"type": "string"
}
}
},
"NewPlant": {
"allOf": [
{
"$ref": "#/components/schemas/Plant"
},
{
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"description": "Identification number of the plant",
"type": "integer",
"format": "int64"
}
}
}
]
},
"Error": {
"required": [
"error",
"message"
],
"type": "object",
"properties": {
"error": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
}
},
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer"
}
}
}
}

View File

@@ -0,0 +1,276 @@
---
title: "OpenAPI Integration"
description: "Generate OpenAPI specifications from MCP tools for seamless integration with OpenWebUI and other systems"
---
# OpenAPI Generation for OpenWebUI Integration
MCPHub now supports generating OpenAPI 3.0.3 specifications from MCP tools, enabling seamless integration with OpenWebUI and other OpenAPI-compatible systems without requiring MCPO as an intermediary proxy.
## Features
- ✅ **Automatic OpenAPI Generation**: Converts MCP tools to OpenAPI 3.0.3 specification
- ✅ **OpenWebUI Compatible**: Direct integration without MCPO proxy
- ✅ **Real-time Tool Discovery**: Dynamically includes tools from connected MCP servers
- ✅ **Dual Parameter Support**: Supports both GET (query params) and POST (JSON body) for tool execution
- ✅ **No Authentication Required**: OpenAPI endpoints are public for easy integration
- ✅ **Comprehensive Metadata**: Full OpenAPI specification with proper schemas and documentation
## API Endpoints
### OpenAPI Specification
<CodeGroup>
```bash GET /api/openapi.json
curl "http://localhost:3000/api/openapi.json"
```
```bash With Parameters
curl "http://localhost:3000/api/openapi.json?title=My MCP API&version=2.0.0"
```
</CodeGroup>
Generates and returns the complete OpenAPI 3.0.3 specification for all connected MCP tools.
**Query Parameters:**
<ParamField query="title" type="string" optional>
Custom API title
</ParamField>
<ParamField query="description" type="string" optional>
Custom API description
</ParamField>
<ParamField query="version" type="string" optional>
Custom API version
</ParamField>
<ParamField query="serverUrl" type="string" optional>
Custom server URL
</ParamField>
<ParamField query="includeDisabled" type="boolean" optional default="false">
Include disabled tools
</ParamField>
<ParamField query="servers" type="string" optional>
Comma-separated list of server names to include
</ParamField>
### Group/Server-Specific OpenAPI Specification
<CodeGroup>
```bash GET /api/:name/openapi.json
curl "http://localhost:3000/api/mygroup/openapi.json"
```
```bash With Parameters
curl "http://localhost:3000/api/myserver/openapi.json?title=My Server API&version=1.0.0"
```
</CodeGroup>
Generates and returns the OpenAPI 3.0.3 specification for a specific group or server. If a group with the given name exists, it returns the specification for all servers in that group. Otherwise, it treats the name as a server name and returns the specification for that server only.
**Path Parameters:**
<ParamField path="name" type="string" required>
Group ID/name or server name
</ParamField>
**Query Parameters:**
Same as the main OpenAPI specification endpoint (title, description, version, serverUrl, includeDisabled).
### Available Servers
<CodeGroup>
```bash GET /api/openapi/servers
curl "http://localhost:3000/api/openapi/servers"
```
</CodeGroup>
Returns a list of connected MCP server names.
<ResponseExample>
```json Example Response
{
"success": true,
"data": ["amap", "playwright", "slack"]
}
```
</ResponseExample>
### Tool Statistics
<CodeGroup>
```bash GET /api/openapi/stats
curl "http://localhost:3000/api/openapi/stats"
```
</CodeGroup>
Returns statistics about available tools and servers.
<ResponseExample>
```json Example Response
{
"success": true,
"data": {
"totalServers": 3,
"totalTools": 41,
"serverBreakdown": [
{"name": "amap", "toolCount": 12, "status": "connected"},
{"name": "playwright", "toolCount": 21, "status": "connected"},
{"name": "slack", "toolCount": 8, "status": "connected"}
]
}
}
```
</ResponseExample>
### Tool Execution
<CodeGroup>
```bash GET /api/tools/{serverName}/{toolName}
curl "http://localhost:3000/api/tools/amap/amap-maps_weather?city=Beijing"
```
```bash POST /api/tools/{serverName}/{toolName}
curl -X POST "http://localhost:3000/api/tools/playwright/playwright-browser_navigate" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
```
</CodeGroup>
Execute MCP tools via OpenAPI-compatible endpoints.
**Path Parameters:**
<ParamField path="serverName" type="string" required>
The name of the MCP server
</ParamField>
<ParamField path="toolName" type="string" required>
The name of the tool to execute
</ParamField>
## OpenWebUI Integration
To integrate MCPHub with OpenWebUI:
<Steps>
<Step title="Start MCPHub">
Ensure MCPHub is running with your MCP servers configured
</Step>
<Step title="Get OpenAPI Specification">
```bash
curl http://localhost:3000/api/openapi.json > mcphub-api.json
```
</Step>
<Step title="Add to OpenWebUI">
Import the OpenAPI specification file or point to the URL directly in OpenWebUI
</Step>
</Steps>
### Configuration Example
In OpenWebUI, you can add MCPHub as an OpenAPI tool by using:
<CardGroup cols={2}>
<Card title="OpenAPI URL" icon="link">
`http://localhost:3000/api/openapi.json`
</Card>
<Card title="Base URL" icon="server">
`http://localhost:3000/api`
</Card>
</CardGroup>
## Generated OpenAPI Structure
The generated OpenAPI specification includes:
### Tool Conversion Logic
- **Simple tools** (≤10 primitive parameters) → GET endpoints with query parameters
- **Complex tools** (objects, arrays, or >10 parameters) → POST endpoints with JSON request body
- **All tools** include comprehensive response schemas and error handling
### Example Generated Operation
```yaml
/tools/amap/amap-maps_weather:
get:
summary: "根据城市名称或者标准adcode查询指定城市的天气"
operationId: "amap_amap-maps_weather"
tags: ["amap"]
parameters:
- name: city
in: query
required: true
description: "城市名称或者adcode"
schema:
type: string
responses:
'200':
description: "Successful tool execution"
content:
application/json:
schema:
$ref: '#/components/schemas/ToolResponse'
```
### Security
- Bearer authentication is defined but not enforced for tool execution endpoints
- Enables flexible integration with various OpenAPI-compatible systems
## Benefits over MCPO
<CardGroup cols={2}>
<Card title="Direct Integration" icon="plug">
No need for intermediate proxy
</Card>
<Card title="Real-time Updates" icon="refresh">
OpenAPI spec updates automatically as MCP servers connect/disconnect
</Card>
<Card title="Better Performance" icon="bolt">
Direct tool execution without proxy overhead
</Card>
<Card title="Simplified Architecture" icon="layer-group">
One less component to manage
</Card>
</CardGroup>
## Troubleshooting
<AccordionGroup>
<Accordion title="OpenAPI spec shows no tools">
Ensure MCP servers are connected. Check `/api/openapi/stats` for server status.
</Accordion>
<Accordion title="Tool execution fails">
Verify the tool name and parameters match the OpenAPI specification. Check server logs for details.
</Accordion>
<Accordion title="OpenWebUI can't connect">
Ensure MCPHub is accessible from OpenWebUI and the OpenAPI URL is correct.
</Accordion>
<Accordion title="Missing tools in specification">
Check if tools are enabled in your MCP server configuration. Use `includeDisabled=true` to see all tools.
</Accordion>
</AccordionGroup>

View File

@@ -0,0 +1,142 @@
---
title: "Prompts"
description: "Manage and execute MCP prompts."
---
import { Card, Cards } from 'mintlify';
<Card
title="POST /api/mcp/:serverName/prompts/:promptName"
href="#get-a-prompt"
>
Execute a prompt on an MCP server.
</Card>
<Card
title="POST /api/servers/:serverName/prompts/:promptName/toggle"
href="#toggle-a-prompt"
>
Enable or disable a prompt.
</Card>
<Card
title="PUT /api/servers/:serverName/prompts/:promptName/description"
href="#update-prompt-description"
>
Update the description of a prompt.
</Card>
---
### Get a Prompt
Execute a prompt on an MCP server and get the result.
- **Endpoint**: `/api/mcp/:serverName/prompts/:promptName`
- **Method**: `POST`
- **Authentication**: Required
- **Parameters**:
- `:serverName` (string, required): The name of the MCP server.
- `:promptName` (string, required): The name of the prompt.
- **Body**:
```json
{
"arguments": {
"arg1": "value1",
"arg2": "value2"
}
}
```
- `arguments` (object, optional): Arguments to pass to the prompt.
- **Response**:
```json
{
"success": true,
"data": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "Prompt content"
}
}
]
}
}
```
**Example Request:**
```bash
curl -X POST "http://localhost:3000/api/mcp/myserver/prompts/code-review" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"arguments": {
"language": "typescript",
"code": "const x = 1;"
}
}'
```
---
### Toggle a Prompt
Enable or disable a specific prompt on a server.
- **Endpoint**: `/api/servers/:serverName/prompts/:promptName/toggle`
- **Method**: `POST`
- **Authentication**: Required
- **Parameters**:
- `:serverName` (string, required): The name of the server.
- `:promptName` (string, required): The name of the prompt.
- **Body**:
```json
{
"enabled": true
}
```
- `enabled` (boolean, required): `true` to enable the prompt, `false` to disable it.
**Example Request:**
```bash
curl -X POST "http://localhost:3000/api/servers/myserver/prompts/code-review/toggle" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"enabled": false}'
```
---
### Update Prompt Description
Update the description of a specific prompt.
- **Endpoint**: `/api/servers/:serverName/prompts/:promptName/description`
- **Method**: `PUT`
- **Authentication**: Required
- **Parameters**:
- `:serverName` (string, required): The name of the server.
- `:promptName` (string, required): The name of the prompt.
- **Body**:
```json
{
"description": "New prompt description"
}
```
- `description` (string, required): The new description for the prompt.
**Example Request:**
```bash
curl -X PUT "http://localhost:3000/api/servers/myserver/prompts/code-review/description" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"description": "Review code for best practices and potential issues"}'
```
**Note**: Prompts are templates that can be used to generate standardized requests to MCP servers. They are defined by the MCP server and can have arguments that are filled in when the prompt is executed.

View File

@@ -0,0 +1,265 @@
---
title: "Servers"
description: "Manage your MCP servers."
---
import { Card, Cards } from 'mintlify';
<Card
title="GET /api/servers"
href="#get-all-servers"
>
Get a list of all MCP servers.
</Card>
<Card
title="POST /api/servers"
href="#create-a-new-server"
>
Create a new MCP server.
</Card>
<Card
title="PUT /api/servers/:name"
href="#update-a-server"
>
Update an existing MCP server.
</Card>
<Card
title="DELETE /api/servers/:name"
href="#delete-a-server"
>
Delete an MCP server.
</Card>
<Card
title="POST /api/servers/:name/toggle"
href="#toggle-a-server"
>
Toggle the enabled state of a server.
</Card>
<Card
title="POST /api/servers/:serverName/tools/:toolName/toggle"
href="#toggle-a-tool"
>
Toggle the enabled state of a tool.
</Card>
<Card
title="PUT /api/servers/:serverName/tools/:toolName/description"
href="#update-tool-description"
>
Update the description of a tool.
</Card>
<Card
title="PUT /api/system-config"
href="#update-system-config"
>
Update system configuration settings.
</Card>
<Card
title="GET /api/settings"
href="#get-settings"
>
Get all server settings and configurations.
</Card>
---
### Get All Servers
Retrieves a list of all configured MCP servers, including their status and available tools.
- **Endpoint**: `/api/servers`
- **Method**: `GET`
- **Response**:
```json
{
"success": true,
"data": [
{
"name": "example-server",
"status": "connected",
"tools": [
{
"name": "tool1",
"description": "Description of tool 1"
}
],
"config": {
"type": "stdio",
"command": "node",
"args": ["server.js"]
}
}
]
}
```
---
### Create a New Server
Adds a new MCP server to the configuration.
- **Endpoint**: `/api/servers`
- **Method**: `POST`
- **Body**:
```json
{
"name": "my-new-server",
"config": {
"type": "stdio",
"command": "python",
"args": ["-u", "my_script.py"],
"owner": "admin"
}
}
```
- `name` (string, required): The unique name for the server.
- `config` (object, required): The server configuration object.
- `type` (string): `stdio`, `sse`, `streamable-http`, or `openapi`.
- `command` (string): Command to execute for `stdio` type.
- `args` (array of strings): Arguments for the command.
- `url` (string): URL for `sse`, `streamable-http`, or `openapi` types.
- `openapi` (object): OpenAPI configuration.
- `url` (string): URL to the OpenAPI schema.
- `schema` (object): The OpenAPI schema object itself.
- `headers` (object): Headers to send with requests for `sse`, `streamable-http`, and `openapi` types.
- `keepAliveInterval` (number): Keep-alive interval in milliseconds for `sse` type. Defaults to 60000.
- `owner` (string): The owner of the server. Defaults to the current user or 'admin'.
---
### Update a Server
Updates the configuration of an existing MCP server.
- **Endpoint**: `/api/servers/:name`
- **Method**: `PUT`
- **Parameters**:
- `:name` (string, required): The name of the server to update.
- **Body**:
```json
{
"config": {
"type": "stdio",
"command": "node",
"args": ["new_server.js"]
}
}
```
- `config` (object, required): The updated server configuration object. See "Create a New Server" for details.
---
### Delete a Server
Removes an MCP server from the configuration.
- **Endpoint**: `/api/servers/:name`
- **Method**: `DELETE`
- **Parameters**:
- `:name` (string, required): The name of the server to delete.
---
### Toggle a Server
Enables or disables an MCP server.
- **Endpoint**: `/api/servers/:name/toggle`
- **Method**: `POST`
- **Parameters**:
- `:name` (string, required): The name of the server to toggle.
- **Body**:
```json
{
"enabled": true
}
```
- `enabled` (boolean, required): `true` to enable the server, `false` to disable it.
---
### Toggle a Tool
Enables or disables a specific tool on a server.
- **Endpoint**: `/api/servers/:serverName/tools/:toolName/toggle`
- **Method**: `POST`
- **Parameters**:
- `:serverName` (string, required): The name of the server.
- `:toolName` (string, required): The name of the tool.
- **Body**:
```json
{
"enabled": true
}
```
- `enabled` (boolean, required): `true` to enable the tool, `false` to disable it.
---
### Update Tool Description
Updates the description of a specific tool.
- **Endpoint**: `/api/servers/:serverName/tools/:toolName/description`
- **Method**: `PUT`
- **Parameters**:
- `:serverName` (string, required): The name of the server.
- `:toolName` (string, required): The name of the tool.
- **Body**:
```json
{
"description": "New tool description"
}
```
- `description` (string, required): The new description for the tool.
---
### Update System Config
Updates the system-wide configuration settings.
- **Endpoint**: `/api/system-config`
- **Method**: `PUT`
- **Body**:
```json
{
"openaiApiKey": "sk-...",
"openaiBaseUrl": "https://api.openai.com/v1",
"modelName": "gpt-4",
"temperature": 0.7,
"maxTokens": 2048
}
```
- All fields are optional. Only provided fields will be updated.
---
### Get Settings
Retrieves all server settings and configurations.
- **Endpoint**: `/api/settings`
- **Method**: `GET`
- **Response**:
```json
{
"success": true,
"data": {
"servers": [...],
"groups": [...],
"systemConfig": {...}
}
}
```
**Note**: For detailed prompt management, see the [Prompts API](/api-reference/prompts) documentation.

View File

@@ -0,0 +1,29 @@
---
title: "Smart Routing"
description: "Intelligent tool discovery using vector semantic search."
---
Smart Routing is MCPHub's intelligent tool discovery system that uses vector semantic search to automatically find the most relevant tools for any given task.
### HTTP Endpoint
- **Endpoint**: `http://localhost:3000/mcp/$smart`
- **Method**: `POST`
### SSE Endpoint (Deprecated)
- **Endpoint**: `http://localhost:3000/sse/$smart`
- **Method**: `GET`
### How it Works
1. **Tool Indexing**: All MCP tools are automatically converted to vector embeddings and stored in PostgreSQL with pgvector.
2. **Semantic Search**: User queries are converted to vectors and matched against tool embeddings using cosine similarity.
3. **Intelligent Filtering**: Dynamic thresholds ensure relevant results without noise.
4. **Precise Execution**: Found tools can be directly executed with proper parameter validation.
### Setup Requirements
- PostgreSQL with pgvector extension
- OpenAI API key (or compatible embedding service)
- Enable Smart Routing in MCPHub settings

View File

@@ -0,0 +1,113 @@
---
title: "System"
description: "System and utility endpoints."
---
import { Card, Cards } from 'mintlify';
<Card
title="GET /health"
href="#health-check"
>
Check the health status of the MCPHub server.
</Card>
<Card
title="GET /oauth/callback"
href="#oauth-callback"
>
OAuth callback endpoint for authentication flows.
</Card>
<Card
title="POST /api/dxt/upload"
href="#upload-dxt-file"
>
Upload a DXT configuration file.
</Card>
<Card
title="GET /api/mcp-settings/export"
href="#export-mcp-settings"
>
Export MCP settings as JSON.
</Card>
---
### Health Check
Check the health status of the MCPHub server.
- **Endpoint**: `/health`
- **Method**: `GET`
- **Authentication**: Not required
- **Response**:
```json
{
"status": "ok",
"timestamp": "2024-11-12T01:30:00.000Z",
"uptime": 12345
}
```
**Example Request:**
```bash
curl "http://localhost:3000/health"
```
---
### OAuth Callback
OAuth callback endpoint for handling OAuth authentication flows. This endpoint is automatically called by OAuth providers after user authorization.
- **Endpoint**: `/oauth/callback`
- **Method**: `GET`
- **Authentication**: Not required (public callback URL)
- **Query Parameters**: Varies by OAuth provider (typically includes `code`, `state`, etc.)
**Note**: This endpoint is used internally by MCPHub's OAuth integration and should not be called directly by clients.
---
### Upload DXT File
Upload a DXT (Desktop Extension) configuration file to import server configurations.
- **Endpoint**: `/api/dxt/upload`
- **Method**: `POST`
- **Authentication**: Required
- **Content-Type**: `multipart/form-data`
- **Body**:
- `file` (file, required): The DXT configuration file to upload.
**Example Request:**
```bash
curl -X POST "http://localhost:3000/api/dxt/upload" \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "file=@config.dxt"
```
---
### Export MCP Settings
Export the current MCP settings configuration as a JSON file.
- **Endpoint**: `/api/mcp-settings/export`
- **Method**: `GET`
- **Authentication**: Required
- **Response**: Returns the `mcp_settings.json` configuration file.
**Example Request:**
```bash
curl "http://localhost:3000/api/mcp-settings/export" \
-H "Authorization: Bearer YOUR_TOKEN" \
-o mcp_settings.json
```
**Note**: This endpoint allows you to download a backup of your MCP settings, which can be used to restore or migrate your configuration.

View File

@@ -0,0 +1,86 @@
---
title: "Tools"
description: "Execute MCP tools programmatically."
---
import { Card, Cards } from 'mintlify';
<Card
title="POST /api/tools/call/:server"
href="#call-a-tool"
>
Call a specific tool on an MCP server.
</Card>
---
### Call a Tool
Execute a specific tool on an MCP server with given arguments.
- **Endpoint**: `/api/tools/call/:server`
- **Method**: `POST`
- **Parameters**:
- `:server` (string, required): The name of the MCP server.
- **Body**:
```json
{
"toolName": "tool-name",
"arguments": {
"param1": "value1",
"param2": "value2"
}
}
```
- `toolName` (string, required): The name of the tool to execute.
- `arguments` (object, optional): The arguments to pass to the tool. Defaults to an empty object.
- **Response**:
```json
{
"success": true,
"data": {
"content": [
{
"type": "text",
"text": "Tool execution result"
}
],
"toolName": "tool-name",
"arguments": {
"param1": "value1",
"param2": "value2"
}
}
}
```
**Example Request:**
```bash
curl -X POST "http://localhost:3000/api/tools/call/amap" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"toolName": "amap-maps_weather",
"arguments": {
"city": "Beijing"
}
}'
```
**Notes:**
- The tool arguments are automatically converted to the proper types based on the tool's input schema.
- Use the `x-session-id` header to maintain session state across multiple tool calls if needed.
- This endpoint requires authentication.
---
### Alternative: OpenAPI Tool Execution
For OpenAPI-compatible tool execution without authentication, see the [OpenAPI Integration](/api-reference/openapi#tool-execution) documentation. The OpenAPI endpoints provide:
- **GET** `/api/tools/:serverName/:toolName` - For simple tools with query parameters
- **POST** `/api/tools/:serverName/:toolName` - For complex tools with JSON body
These endpoints are designed for integration with OpenWebUI and other OpenAPI-compatible systems.

View File

@@ -0,0 +1,195 @@
---
title: "Users"
description: "Manage users in MCPHub."
---
import { Card, Cards } from 'mintlify';
<Card
title="GET /api/users"
href="#get-all-users"
>
Get a list of all users.
</Card>
<Card
title="GET /api/users/:username"
href="#get-a-user"
>
Get details of a specific user.
</Card>
<Card
title="POST /api/users"
href="#create-a-user"
>
Create a new user.
</Card>
<Card
title="PUT /api/users/:username"
href="#update-a-user"
>
Update an existing user.
</Card>
<Card
title="DELETE /api/users/:username"
href="#delete-a-user"
>
Delete a user.
</Card>
<Card
title="GET /api/users-stats"
href="#get-user-statistics"
>
Get statistics about users and their server access.
</Card>
---
### Get All Users
Retrieves a list of all users in the system.
- **Endpoint**: `/api/users`
- **Method**: `GET`
- **Authentication**: Required (Admin only)
- **Response**:
```json
{
"success": true,
"data": [
{
"username": "admin",
"role": "admin",
"servers": ["server1", "server2"],
"groups": ["group1"]
},
{
"username": "user1",
"role": "user",
"servers": ["server1"],
"groups": []
}
]
}
```
---
### Get a User
Retrieves details of a specific user.
- **Endpoint**: `/api/users/:username`
- **Method**: `GET`
- **Authentication**: Required (Admin only)
- **Parameters**:
- `:username` (string, required): The username of the user.
- **Response**:
```json
{
"success": true,
"data": {
"username": "user1",
"role": "user",
"servers": ["server1", "server2"],
"groups": ["group1"]
}
}
```
---
### Create a User
Creates a new user in the system.
- **Endpoint**: `/api/users`
- **Method**: `POST`
- **Authentication**: Required (Admin only)
- **Body**:
```json
{
"username": "newuser",
"password": "securepassword",
"role": "user",
"servers": ["server1"],
"groups": ["group1"]
}
```
- `username` (string, required): The username for the new user.
- `password` (string, required): The password for the new user. Must be at least 6 characters.
- `role` (string, optional): The role of the user. Either `"admin"` or `"user"`. Defaults to `"user"`.
- `servers` (array of strings, optional): List of server names the user has access to.
- `groups` (array of strings, optional): List of group IDs the user belongs to.
---
### Update a User
Updates an existing user's information.
- **Endpoint**: `/api/users/:username`
- **Method**: `PUT`
- **Authentication**: Required (Admin only)
- **Parameters**:
- `:username` (string, required): The username of the user to update.
- **Body**:
```json
{
"password": "newpassword",
"role": "admin",
"servers": ["server1", "server2", "server3"],
"groups": ["group1", "group2"]
}
```
- `password` (string, optional): New password for the user.
- `role` (string, optional): New role for the user.
- `servers` (array of strings, optional): Updated list of accessible servers.
- `groups` (array of strings, optional): Updated list of groups.
---
### Delete a User
Removes a user from the system.
- **Endpoint**: `/api/users/:username`
- **Method**: `DELETE`
- **Authentication**: Required (Admin only)
- **Parameters**:
- `:username` (string, required): The username of the user to delete.
---
### Get User Statistics
Retrieves statistics about users and their access to servers and groups.
- **Endpoint**: `/api/users-stats`
- **Method**: `GET`
- **Authentication**: Required (Admin only)
- **Response**:
```json
{
"success": true,
"data": {
"totalUsers": 5,
"adminUsers": 1,
"regularUsers": 4,
"usersPerServer": {
"server1": 3,
"server2": 2
},
"usersPerGroup": {
"group1": 2,
"group2": 1
}
}
}
```
**Note**: All user management endpoints require admin authentication.

View File

@@ -0,0 +1,583 @@
---
title: 'Docker Setup'
description: 'Deploy MCPHub using Docker and Docker Compose'
---
# Docker Setup
This guide covers deploying MCPHub using Docker, including development and production configurations.
## Quick Start with Docker
### Using Pre-built Image
```bash
# Pull the latest image
docker pull mcphub/mcphub:latest
# Run with default configuration
docker run -d \
--name mcphub \
-p 3000:3000 \
-v $(pwd)/mcp_settings.json:/app/mcp_settings.json \
mcphub/mcphub:latest
```
### Building from Source
```bash
# Clone the repository
git clone https://github.com/your-username/mcphub.git
cd mcphub
# Build the Docker image
docker build -t mcphub:local .
# Run the container
docker run -d \
--name mcphub \
-p 3000:3000 \
-v $(pwd)/mcp_settings.json:/app/mcp_settings.json \
mcphub:local
```
### Building with Extended Features
The Docker image supports an `INSTALL_EXT` build argument to include additional tools:
```bash
# Build with extended features (includes Docker Engine, Chrome/Playwright)
docker build --build-arg INSTALL_EXT=true -t mcphub:extended .
# Option 1: Run with automatic Docker-in-Docker (requires privileged mode)
docker run -d \
--name mcphub \
--privileged \
-p 3000:3000 \
-v $(pwd)/mcp_settings.json:/app/mcp_settings.json \
mcphub:extended
# Option 2: Run with Docker socket mounted (use host's Docker daemon)
docker run -d \
--name mcphub \
-p 3000:3000 \
-v $(pwd)/mcp_settings.json:/app/mcp_settings.json \
-v /var/run/docker.sock:/var/run/docker.sock \
mcphub:extended
# Verify Docker is available
docker exec mcphub docker --version
docker exec mcphub docker ps
```
<Note>
**What's included with INSTALL_EXT=true:**
- **Docker Engine**: Full Docker daemon with CLI for container management. The daemon auto-starts when the container runs in privileged mode.
- **Chrome/Playwright** (amd64 only): For browser automation tasks
The extended image is larger but provides additional capabilities for advanced use cases.
</Note>
<Warning>
**Docker-in-Docker Security Considerations:**
- **Privileged mode** (`--privileged`): Required for the Docker daemon to start inside the container. This gives the container elevated permissions on the host.
- **Docker socket mounting** (`/var/run/docker.sock`): Gives the container access to the host's Docker daemon. Both approaches should only be used in trusted environments.
- For production, consider using Docker socket mounting instead of privileged mode for better security.
</Warning>
## Docker Compose Setup
### Basic Configuration
Create a `docker-compose.yml` file:
```yaml
version: '3.8'
services:
mcphub:
image: mcphub/mcphub:latest
# For local development, use:
# build: .
container_name: mcphub
ports:
- '3000:3000'
environment:
- NODE_ENV=production
- PORT=3000
- JWT_SECRET=${JWT_SECRET:-your-jwt-secret}
- DATABASE_URL=postgresql://mcphub:password@postgres:5432/mcphub
volumes:
- ./mcp_settings.json:/app/mcp_settings.json:ro
- ./servers.json:/app/servers.json:ro
- mcphub_data:/app/data
depends_on:
postgres:
condition: service_healthy
restart: unless-stopped
networks:
- mcphub-network
postgres:
image: postgres:15-alpine
container_name: mcphub-postgres
environment:
- POSTGRES_DB=mcphub
- POSTGRES_USER=mcphub
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data
- ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql:ro
ports:
- '5432:5432'
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U mcphub -d mcphub']
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- mcphub-network
volumes:
postgres_data:
mcphub_data:
networks:
mcphub-network:
driver: bridge
```
### Production Configuration with Nginx
```yaml
version: '3.8'
services:
nginx:
image: nginx:alpine
container_name: mcphub-nginx
ports:
- '80:80'
- '443:443'
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./ssl:/etc/nginx/ssl:ro
- nginx_logs:/var/log/nginx
depends_on:
- mcphub
restart: unless-stopped
networks:
- mcphub-network
mcphub:
image: mcphub/mcphub:latest
container_name: mcphub-app
expose:
- '3000'
environment:
- NODE_ENV=production
- PORT=3000
- JWT_SECRET=${JWT_SECRET}
- JWT_EXPIRES_IN=${JWT_EXPIRES_IN:-24h}
- DATABASE_URL=postgresql://mcphub:${POSTGRES_PASSWORD}@postgres:5432/mcphub
- OPENAI_API_KEY=${OPENAI_API_KEY}
- REDIS_URL=redis://redis:6379
volumes:
- ./mcp_settings.json:/app/mcp_settings.json:ro
- ./servers.json:/app/servers.json:ro
- mcphub_data:/app/data
- mcphub_logs:/app/logs
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
restart: unless-stopped
networks:
- mcphub-network
healthcheck:
test: ['CMD', 'wget', '--quiet', '--tries=1', '--spider', 'http://localhost:3000/health']
interval: 30s
timeout: 10s
retries: 3
postgres:
image: postgres:15-alpine
container_name: mcphub-postgres
environment:
- POSTGRES_DB=mcphub
- POSTGRES_USER=mcphub
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./backups:/backups
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U mcphub -d mcphub']
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- mcphub-network
redis:
image: redis:7-alpine
container_name: mcphub-redis
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- mcphub-network
volumes:
postgres_data:
redis_data:
mcphub_data:
mcphub_logs:
nginx_logs:
networks:
mcphub-network:
driver: bridge
```
### Environment Variables
Create a `.env` file for Docker Compose:
```env
# Application
NODE_ENV=production
JWT_SECRET=your-super-secret-jwt-key-change-this
JWT_EXPIRES_IN=24h
# Database
POSTGRES_PASSWORD=your-secure-database-password
# Redis
REDIS_PASSWORD=your-secure-redis-password
# External APIs
OPENAI_API_KEY=your-openai-api-key
# Optional: Custom port
# PORT=3000
```
## Development Setup
### Development Docker Compose
Create `docker-compose.dev.yml`:
```yaml
version: '3.8'
services:
mcphub-dev:
build:
context: .
dockerfile: Dockerfile.dev
container_name: mcphub-dev
ports:
- '3000:3000'
- '5173:5173' # Frontend dev server
- '9229:9229' # Debug port
environment:
- NODE_ENV=development
- PORT=3000
- DATABASE_URL=postgresql://mcphub:password@postgres:5432/mcphub
volumes:
- .:/app
- /app/node_modules
- /app/frontend/node_modules
depends_on:
- postgres
command: pnpm dev
networks:
- mcphub-dev
postgres:
image: postgres:15-alpine
container_name: mcphub-postgres-dev
environment:
- POSTGRES_DB=mcphub
- POSTGRES_USER=mcphub
- POSTGRES_PASSWORD=password
ports:
- '5432:5432'
volumes:
- postgres_dev_data:/var/lib/postgresql/data
networks:
- mcphub-dev
volumes:
postgres_dev_data:
networks:
mcphub-dev:
driver: bridge
```
### Development Dockerfile
Create `Dockerfile.dev`:
```dockerfile
FROM node:20-alpine
# Install pnpm
RUN npm install -g pnpm
# Set working directory
WORKDIR /app
# Copy package files
COPY package.json pnpm-lock.yaml ./
COPY frontend/package.json ./frontend/
# Install dependencies
RUN pnpm install
# Copy source code
COPY . .
# Expose ports
EXPOSE 3000 5173 9229
# Start development server
CMD ["pnpm", "dev"]
```
## Running the Application
### Development Mode
```bash
# Start development environment
docker-compose -f docker-compose.dev.yml up -d
# View logs
docker-compose -f docker-compose.dev.yml logs -f mcphub-dev
# Stop development environment
docker-compose -f docker-compose.dev.yml down
```
### Production Mode
```bash
# Start production environment
docker-compose up -d
# View logs
docker-compose logs -f mcphub
# Stop production environment
docker-compose down
```
## Configuration Management
### MCP Settings Volume Mount
Create your `mcp_settings.json`:
```json
{
"mcpServers": {
"fetch": {
"command": "uvx",
"args": ["mcp-server-fetch"]
},
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest", "--headless"]
},
"amap": {
"command": "npx",
"args": ["-y", "@amap/amap-maps-mcp-server"],
"env": {
"AMAP_MAPS_API_KEY": "your-api-key"
}
}
}
}
```
### Secrets Management
For production, use Docker secrets:
```yaml
version: '3.8'
services:
mcphub:
image: mcphub/mcphub:latest
environment:
- JWT_SECRET_FILE=/run/secrets/jwt_secret
- DATABASE_PASSWORD_FILE=/run/secrets/db_password
secrets:
- jwt_secret
- db_password
secrets:
jwt_secret:
file: ./secrets/jwt_secret.txt
db_password:
file: ./secrets/db_password.txt
```
## Data Persistence
### Database Backups
Add backup service to your `docker-compose.yml`:
```yaml
services:
backup:
image: postgres:15-alpine
container_name: mcphub-backup
environment:
- PGPASSWORD=${POSTGRES_PASSWORD}
volumes:
- ./backups:/backups
- ./scripts/backup.sh:/backup.sh:ro
command: /bin/sh -c "chmod +x /backup.sh && /backup.sh"
depends_on:
- postgres
profiles:
- backup
networks:
- mcphub-network
```
Create `scripts/backup.sh`:
```bash
#!/bin/sh
BACKUP_FILE="/backups/mcphub_$(date +%Y%m%d_%H%M%S).sql"
pg_dump -h postgres -U mcphub -d mcphub > "$BACKUP_FILE"
echo "Backup created: $BACKUP_FILE"
# Keep only last 7 days of backups
find /backups -name "mcphub_*.sql" -mtime +7 -delete
```
Run backup:
```bash
docker-compose --profile backup run --rm backup
```
## Monitoring and Health Checks
### Health Check Endpoint
Add to your application:
```javascript
// In your Express app
app.get('/health', (req, res) => {
res.json({
status: 'healthy',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
memory: process.memoryUsage(),
version: process.env.npm_package_version,
});
});
```
### Docker Health Checks
```yaml
services:
mcphub:
# ... other config
healthcheck:
test: ['CMD', 'wget', '--quiet', '--tries=1', '--spider', 'http://localhost:3000/health']
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
```
### Monitoring with Watchtower
Add automatic updates:
```yaml
services:
watchtower:
image: containrrr/watchtower
container_name: mcphub-watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_POLL_INTERVAL=3600
- WATCHTOWER_INCLUDE_STOPPED=true
restart: unless-stopped
```
## Troubleshooting
### Common Issues
**Container fails to start**: Check logs with `docker-compose logs mcphub`
**Database connection errors**: Ensure PostgreSQL is healthy and accessible
**Port conflicts**: Check if ports 3000/5432 are already in use
**Volume mount issues**: Verify file paths and permissions
### Debug Commands
```bash
# Check container status
docker-compose ps
# View logs
docker-compose logs -f [service_name]
# Execute commands in container
docker-compose exec mcphub sh
# Check database connection
docker-compose exec postgres psql -U mcphub -d mcphub
# Restart specific service
docker-compose restart mcphub
# Rebuild and restart
docker-compose up --build -d
```
### Performance Optimization
```yaml
services:
mcphub:
# ... other config
deploy:
resources:
limits:
memory: 512M
cpus: '0.5'
reservations:
memory: 256M
cpus: '0.25'
```
This Docker setup provides a complete containerized environment for MCPHub with development and production configurations.

View File

@@ -0,0 +1,104 @@
---
title: 'Environment Variables'
description: 'Configure MCPHub using environment variables'
---
# Environment Variables
MCPHub uses environment variables for configuration. This guide covers all available variables and their usage.
## Core Application Settings
### Server Configuration
| Variable | Default | Description |
| --- | --- | --- |
| `PORT` | `3000` | Port number for the HTTP server |
| `INIT_TIMEOUT` | `300000` | Initial timeout for the application |
| `BASE_PATH` | `''` | The base path of the application |
| `READONLY` | `false` | Set to `true` to enable readonly mode |
| `MCPHUB_SETTING_PATH` | | Path to the MCPHub settings |
| `NODE_ENV` | `development` | Application environment (`development`, `production`, `test`) |
```env
PORT=3000
INIT_TIMEOUT=300000
BASE_PATH=/api
READONLY=true
MCPHUB_SETTING_PATH=/path/to/settings
NODE_ENV=production
```
## Authentication & Security
### JWT Configuration
| Variable | Default | Description |
| --- | --- | --- |
| `JWT_SECRET` | - | Secret key for JWT token signing (required) |
```env
JWT_SECRET=your-super-secret-key-change-this-in-production
```
## Configuration Examples
### Development Environment
```env
# .env.development
NODE_ENV=development
PORT=3000
# Auth
JWT_SECRET=dev-secret-key
```
### Production Environment
```env
# .env.production
NODE_ENV=production
PORT=3000
# Security
JWT_SECRET=your-super-secure-production-secret
```
### Docker Environment
```env
# .env.docker
NODE_ENV=production
PORT=3000
# Security
JWT_SECRET_FILE=/run/secrets/jwt_secret
```
## Environment Variable Loading
MCPHub loads environment variables in the following order:
1. System environment variables
2. `.env.local` (ignored by git)
3. `.env.{NODE_ENV}` (e.g., `.env.production`)
4. `.env`
### Using dotenv-expand
MCPHub supports variable expansion:
```env
BASE_URL=https://api.example.com
API_ENDPOINT=${BASE_URL}/v1
```
## Security Best Practices
1. **Never commit secrets** to version control
2. **Use strong, unique secrets** for production
3. **Rotate secrets regularly**
4. **Use environment-specific files**
5. **Validate all environment variables** at startup
6. **Use Docker secrets** for container deployments

View File

@@ -0,0 +1,519 @@
---
title: 'MCP Settings Configuration'
description: 'Configure MCP servers and their settings for MCPHub'
---
# MCP Settings Configuration
This guide explains how to configure MCP servers in MCPHub using the `mcp_settings.json` file and related configurations.
## Configuration Files Overview
MCPHub uses several configuration files:
- **`mcp_settings.json`**: Main MCP server configurations
- **`servers.json`**: Server metadata and grouping
- **`.env`**: Environment variables and secrets
## Basic MCP Settings Structure
### mcp_settings.json
```json
{
"mcpServers": {
"server-name": {
"command": "command-to-run",
"args": ["arg1", "arg2"],
"env": {
"ENV_VAR": "value"
}
}
}
}
```
### Example Configuration
```json
{
"mcpServers": {
"fetch": {
"command": "uvx",
"args": ["mcp-server-fetch"],
"env": {
"USER_AGENT": "MCPHub/1.0"
}
},
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest", "--headless"]
},
"slack": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-slack"],
"env": {
"SLACK_BOT_TOKEN": "${SLACK_BOT_TOKEN}",
"SLACK_TEAM_ID": "${SLACK_TEAM_ID}"
}
}
}
}
```
## Server Configuration Options
### Required Fields
| Field | Type | Description |
| --------- | ------ | -------------------------- |
| `command` | string | Executable command or path |
| `args` | array | Command-line arguments |
### Optional Fields
| Field | Type | Default | Description |
| -------------- | ------- | --------------- | --------------------------- |
| `env` | object | `{}` | Environment variables |
## Common MCP Server Examples
### Web and API Servers
#### Fetch Server
```json
{
"fetch": {
"command": "uvx",
"args": ["mcp-server-fetch"],
"env": {
"USER_AGENT": "MCPHub/1.0",
"MAX_REDIRECTS": "10"
}
}
}
```
#### Web Scraping with Playwright
```json
{
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest", "--headless"],
"timeout": 60000,
"env": {
"PLAYWRIGHT_BROWSERS_PATH": "/tmp/browsers"
}
}
}
```
### File and System Servers
#### Filesystem Server
```json
{
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/allowed/path"],
"env": {
"ALLOWED_OPERATIONS": "read,write,list"
}
}
}
```
#### SQLite Server
```json
{
"sqlite": {
"command": "uvx",
"args": ["mcp-server-sqlite", "--db-path", "/path/to/database.db"],
"env": {
"SQLITE_READONLY": "false"
}
}
}
```
### Communication Servers
#### Slack Server
```json
{
"slack": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-slack"],
"env": {
"SLACK_BOT_TOKEN": "${SLACK_BOT_TOKEN}",
"SLACK_TEAM_ID": "${SLACK_TEAM_ID}",
"SLACK_APP_TOKEN": "${SLACK_APP_TOKEN}"
}
}
}
```
#### Email Server
```json
{
"email": {
"command": "python",
"args": ["-m", "mcp_server_email"],
"env": {
"SMTP_HOST": "smtp.gmail.com",
"SMTP_PORT": "587",
"EMAIL_USER": "${EMAIL_USER}",
"EMAIL_PASSWORD": "${EMAIL_PASSWORD}"
}
}
}
```
### Development and API Servers
#### GitHub Server
```json
{
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
}
}
```
#### Google Drive Server
```json
{
"gdrive": {
"command": "npx",
"args": ["-y", "@google/mcp-server-gdrive"],
"env": {
"GOOGLE_CLIENT_ID": "${GOOGLE_CLIENT_ID}",
"GOOGLE_CLIENT_SECRET": "${GOOGLE_CLIENT_SECRET}",
"GOOGLE_REFRESH_TOKEN": "${GOOGLE_REFRESH_TOKEN}"
}
}
}
```
### Map and Location Services
#### Amap (高德地图) Server
```json
{
"amap": {
"command": "npx",
"args": ["-y", "@amap/amap-maps-mcp-server"],
"env": {
"AMAP_MAPS_API_KEY": "${AMAP_API_KEY}",
"AMAP_LANGUAGE": "zh-cn"
}
}
}
```
#### OpenStreetMap Server
```json
{
"osm": {
"command": "python",
"args": ["-m", "mcp_server_osm"],
"env": {
"OSM_USER_AGENT": "MCPHub/1.0"
}
}
}
```
## Advanced Configuration
### Environment Variable Substitution
MCPHub supports environment variable substitution using `${VAR_NAME}` syntax:
```json
{
"mcpServers": {
"api-server": {
"command": "python",
"args": ["-m", "api_server"],
"env": {
"API_KEY": "${API_KEY}",
"API_URL": "${API_BASE_URL}/v1"
}
}
}
}
```
{/* ### Custom Server Scripts
#### Local Python Server
```json
{
"custom-python": {
"command": "python",
"args": ["./servers/custom_server.py"],
"cwd": "/app/custom-servers",
"env": {
"PYTHONPATH": "/app/custom-servers",
"CONFIG_FILE": "./config.json"
}
}
}
```
#### Local Node.js Server
```json
{
"custom-node": {
"command": "node",
"args": ["./servers/custom-server.js"],
"cwd": "/app/custom-servers",
"env": {
"NODE_ENV": "production"
}
}
}
```
## Server Metadata Configuration
### servers.json
Complement `mcp_settings.json` with server metadata:
```json
{
"servers": {
"fetch": {
"name": "Fetch Server",
"description": "HTTP client for web requests",
"category": "web",
"tags": ["http", "api", "web"],
"version": "1.0.0",
"author": "MCPHub Team",
"documentation": "https://docs.mcphub.com/servers/fetch",
"enabled": true
},
"playwright": {
"name": "Playwright Browser",
"description": "Web automation and scraping",
"category": "automation",
"tags": ["browser", "scraping", "automation"],
"version": "2.0.0",
"enabled": true
}
},
"groups": {
"web-tools": {
"name": "Web Tools",
"description": "Tools for web interaction",
"servers": ["fetch", "playwright"],
"access": "public"
},
"admin-tools": {
"name": "Admin Tools",
"description": "Administrative utilities",
"servers": ["filesystem", "database"],
"access": "admin"
}
}
}
``` */}
## Group Management
### Group Configuration
```json
{
"groups": {
"production": {
"name": "Production Tools",
"description": "Stable production servers",
"servers": ["fetch", "slack", "github"]
},
"experimental": {
"name": "Experimental Features",
"description": "Beta and experimental servers",
"servers": ["experimental-ai", "beta-search"]
}
}
}
```
{/* ### Access Control
| Access Level | Description |
| --------------- | -------------------------- |
| `public` | No authentication required |
| `authenticated` | Valid JWT token required |
| `admin` | Admin role required |
| `custom` | Custom permission logic |
## Dynamic Configuration
### Hot Reloading
MCPHub supports hot reloading of configurations:
```bash
# Reload configurations without restart
curl -X POST http://localhost:3000/api/admin/reload-config \
-H "Authorization: Bearer your-admin-token"
``` */}
{/* ### Configuration Validation
MCPHub validates configurations on startup and reload:
```json
{
"validation": {
"strict": true,
"allowUnknownServers": false,
"requireDocumentation": true
}
}
``` */}
## Best Practices
### Security
1. **Use environment variables** for sensitive data:
```json
{
"env": {
"API_KEY": "${API_KEY}",
"DATABASE_PASSWORD": "${DB_PASSWORD}"
}
}
```
{/* 2. **Limit server permissions**:
```json
{
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/restricted/path"],
"env": {
"READONLY": "true"
}
}
}
``` */}
{/* ### Performance
1. **Set appropriate timeouts**:
```json
{
"timeout": 30000,
"maxRestarts": 3,
"restartDelay": 5000
}
```
2. **Resource limits**:
```json
{
"env": {
"NODE_OPTIONS": "--max-old-space-size=512",
"MEMORY_LIMIT": "512MB"
}
}
``` */}
{/* ### Monitoring
1. **Enable health checks**:
```json
{
"healthCheck": {
"enabled": true,
"interval": 30000,
"timeout": 5000
}
}
```
2. **Logging configuration**:
```json
{
"env": {
"LOG_LEVEL": "info",
"LOG_FORMAT": "json"
}
}
``` */}
{/* ## Troubleshooting
### Common Issues
**Server won't start**: Check command and arguments
```bash
# Test command manually
uvx mcp-server-fetch
``` */}
{/* **Environment variables not found**: Verify `.env` file
```bash
# Check environment
printenv | grep API_KEY
```
**Permission errors**: Check file permissions and paths
```bash
# Verify executable permissions
ls -la /path/to/server
``` */}
{/* ### Debug Configuration
Enable debug mode for detailed logging:
```json
{
"debug": {
"enabled": true,
"logLevel": "debug",
"includeEnv": false,
"logStartup": true
}
}
``` */}
{/*
### Validation Errors
Common validation errors and solutions:
1. **Missing required fields**: Add `command` and `args`
2. **Invalid timeout**: Use number, not string
3. **Environment variable not found**: Check `.env` file
4. **Command not found**: Verify installation and PATH */}
This comprehensive guide covers all aspects of configuring MCP servers in MCPHub for various use cases and environments.

View File

@@ -0,0 +1,373 @@
---
title: 'Nginx Configuration'
description: 'Configure Nginx as a reverse proxy for MCPHub'
---
# Nginx Configuration
This guide explains how to configure Nginx as a reverse proxy for MCPHub, including SSL termination, load balancing, and caching strategies.
## Basic Reverse Proxy Setup
### Configuration File
Create or update your Nginx configuration file (`/etc/nginx/sites-available/mcphub`):
```nginx
server {
listen 80;
server_name your-domain.com;
# Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name your-domain.com;
# SSL Configuration
ssl_certificate /path/to/your/certificate.crt;
ssl_certificate_key /path/to/your/private.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# Security Headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Gzip Compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
# Main application
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 86400;
}
# API endpoints with longer timeout for MCP operations
location /api/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 300;
proxy_connect_timeout 60;
proxy_send_timeout 60;
}
# Static assets caching
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
proxy_pass http://127.0.0.1:3000;
proxy_cache_valid 200 1d;
proxy_cache_valid 404 1m;
add_header Cache-Control "public, immutable";
expires 1y;
}
}
```
### Enable the Configuration
```bash
# Create symbolic link to enable the site
sudo ln -s /etc/nginx/sites-available/mcphub /etc/nginx/sites-enabled/
# Test configuration
sudo nginx -t
# Reload Nginx
sudo systemctl reload nginx
```
## Load Balancing Configuration
For high-availability setups with multiple MCPHub instances:
```nginx
upstream mcphub_backend {
least_conn;
server 127.0.0.1:3000 weight=1 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3001 weight=1 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3002 weight=1 max_fails=3 fail_timeout=30s;
# Health check (Nginx Plus feature)
# health_check interval=5s fails=3 passes=2;
}
server {
listen 443 ssl http2;
server_name your-domain.com;
# SSL and other configurations...
location / {
proxy_pass http://mcphub_backend;
# Other proxy settings...
}
}
```
## Caching Configuration
### Browser Caching
```nginx
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
proxy_pass http://127.0.0.1:3000;
expires 1y;
add_header Cache-Control "public, immutable";
}
# Cache API responses (be careful with dynamic content)
location /api/public/ {
proxy_pass http://127.0.0.1:3000;
proxy_cache mcphub_cache;
proxy_cache_valid 200 5m;
proxy_cache_key "$scheme$request_method$host$request_uri";
add_header X-Cache-Status $upstream_cache_status;
}
```
### Nginx Proxy Cache
Add to the `http` block in `nginx.conf`:
```nginx
http {
# Proxy cache configuration
proxy_cache_path /var/cache/nginx/mcphub
levels=1:2
keys_zone=mcphub_cache:10m
max_size=1g
inactive=60m
use_temp_path=off;
# Other configurations...
}
```
## WebSocket Support
For real-time features and SSE (Server-Sent Events):
```nginx
location /api/stream {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Disable buffering for real-time responses
proxy_buffering off;
proxy_cache off;
# Timeouts for long-lived connections
proxy_read_timeout 24h;
proxy_send_timeout 24h;
}
```
## Security Configuration
### Rate Limiting
```nginx
http {
# Define rate limiting zones
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
server {
# Apply rate limiting to API endpoints
location /api/ {
limit_req zone=api burst=20 nodelay;
# Other configurations...
}
# Strict rate limiting for login endpoints
location /api/auth/login {
limit_req zone=login burst=5;
# Other configurations...
}
}
}
```
### IP Whitelisting
```nginx
# Allow specific IPs for admin endpoints
location /api/admin/ {
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
proxy_pass http://127.0.0.1:3000;
# Other proxy settings...
}
```
## Monitoring and Logging
### Access Logs
```nginx
http {
# Custom log format
log_format mcphub_format '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time';
server {
# Enable access logging
access_log /var/log/nginx/mcphub_access.log mcphub_format;
error_log /var/log/nginx/mcphub_error.log;
# Other configurations...
}
}
```
### Status Page
```nginx
location /nginx_status {
stub_status;
allow 127.0.0.1;
deny all;
}
```
## Docker Integration
When running MCPHub in Docker, update the proxy configuration:
```nginx
upstream mcphub_docker {
server mcphub:3000; # Docker service name
}
server {
location / {
proxy_pass http://mcphub_docker;
# Other proxy settings...
}
}
```
## Complete Example Configuration
Here's a production-ready example using the provided `nginx.conf.example`:
```bash
# Copy the example configuration
cp nginx.conf.example /etc/nginx/sites-available/mcphub
# Update the configuration with your domain and paths
sudo nano /etc/nginx/sites-available/mcphub
# Enable the site
sudo ln -s /etc/nginx/sites-available/mcphub /etc/nginx/sites-enabled/
# Test and reload
sudo nginx -t && sudo systemctl reload nginx
```
## Troubleshooting
### Common Issues
**502 Bad Gateway**: Check if MCPHub is running and accessible
**504 Gateway Timeout**: Increase `proxy_read_timeout` for long-running operations
**WebSocket connection failures**: Ensure proper `Upgrade` and `Connection` headers
**Cache issues**: Clear proxy cache or disable for development
### Debug Commands
```bash
# Test Nginx configuration
sudo nginx -t
# Check Nginx status
sudo systemctl status nginx
# View error logs
sudo tail -f /var/log/nginx/error.log
# Check if MCPHub is responding
curl -I http://localhost:3000
```
## Performance Optimization
### Worker Processes
```nginx
# In nginx.conf
worker_processes auto;
worker_connections 1024;
```
### Buffer Sizes
```nginx
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
```
### Keep-Alive
```nginx
upstream mcphub_backend {
server 127.0.0.1:3000;
keepalive 32;
}
location / {
proxy_pass http://mcphub_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
```
This configuration provides a solid foundation for running MCPHub behind Nginx with proper security, performance, and reliability features.

View File

@@ -0,0 +1,210 @@
# MCPHub DAO Layer 实现总结
## 项目概述
本次开发为MCPHub项目引入了独立的数据访问对象(DAO)层,用于管理`mcp_settings.json`中的不同类型数据的增删改查操作。
## 已实现的功能
### 1. 核心DAO层架构
#### 基础架构
- **BaseDao.ts**: 定义了通用的CRUD接口和抽象实现
- **JsonFileBaseDao.ts**: 提供JSON文件操作的基础类包含缓存机制
- **DaoFactory.ts**: 工厂模式实现提供DAO实例的创建和管理
#### 具体DAO实现
1. **UserDao**: 用户数据管理
- 用户创建(含密码哈希)
- 密码验证
- 权限管理
- 管理员查询
2. **ServerDao**: 服务器配置管理
- 服务器CRUD操作
- 按所有者/类型/状态查询
- 工具和提示配置管理
- 启用/禁用控制
3. **GroupDao**: 群组管理
- 群组CRUD操作
- 服务器成员管理
- 按所有者查询
- 群组-服务器关系管理
4. **SystemConfigDao**: 系统配置管理
- 系统级配置的读取和更新
- 分段配置管理
- 配置重置功能
5. **UserConfigDao**: 用户个人配置管理
- 用户个人配置的CRUD操作
- 分段配置管理
- 批量配置查询
### 2. 配置服务集成
#### DaoConfigService
- 使用DAO层重新实现配置加载和保存
- 支持用户权限过滤
- 提供配置合并和验证功能
#### ConfigManager
- 双模式支持:传统文件方式 + 新DAO层
- 运行时切换机制
- 环境变量控制 (`USE_DAO_LAYER`)
- 迁移工具集成
### 3. 迁移和验证工具
#### 迁移功能
- 从传统JSON文件格式迁移到DAO层
- 数据完整性验证
- 性能对比分析
- 迁移报告生成
#### 测试工具
- DAO操作完整性测试
- 示例数据生成和清理
- 性能基准测试
## 文件结构
```
src/
├── dao/ # DAO层核心
│ ├── base/
│ │ ├── BaseDao.ts # 基础DAO接口
│ │ └── JsonFileBaseDao.ts # JSON文件基础类
│ ├── UserDao.ts # 用户数据访问
│ ├── ServerDao.ts # 服务器配置访问
│ ├── GroupDao.ts # 群组数据访问
│ ├── SystemConfigDao.ts # 系统配置访问
│ ├── UserConfigDao.ts # 用户配置访问
│ ├── DaoFactory.ts # DAO工厂
│ ├── examples.ts # 使用示例
│ └── index.ts # 统一导出
├── config/
│ ├── DaoConfigService.ts # DAO配置服务
│ ├── configManager.ts # 配置管理器
│ └── migrationUtils.ts # 迁移工具
├── scripts/
│ └── dao-demo.ts # 演示脚本
└── docs/
└── dao-layer.md # 详细文档
```
## 主要特性
### 1. 类型安全
- 完整的TypeScript类型定义
- 编译时类型检查
- 接口约束和验证
### 2. 模块化设计
- 每种数据类型独立的DAO
- 清晰的关注点分离
- 可插拔的实现方式
### 3. 缓存机制
- JSON文件读取缓存
- 文件修改时间检测
- 缓存失效和刷新
### 4. 向后兼容
- 保持现有API不变
- 支持传统和DAO双模式
- 平滑迁移路径
### 5. 未来扩展性
- 数据库切换准备
- 新数据类型支持
- 复杂查询能力
## 使用方法
### 启用DAO层
```bash
# 环境变量配置
export USE_DAO_LAYER=true
```
### 基本操作示例
```typescript
import { getUserDao, getServerDao } from './dao/index.js';
// 用户操作
const userDao = getUserDao();
await userDao.createWithHashedPassword('admin', 'password', true);
const user = await userDao.findByUsername('admin');
// 服务器操作
const serverDao = getServerDao();
await serverDao.create({
name: 'my-server',
command: 'node',
args: ['server.js']
});
```
### 迁移操作
```typescript
import { migrateToDao, validateMigration } from './config/configManager.js';
// 执行迁移
await migrateToDao();
// 验证迁移
await validateMigration();
```
## 依赖包
新增的依赖包:
- `bcrypt`: 用户密码哈希
- `@types/bcrypt`: bcrypt类型定义
- `uuid`: UUID生成群组ID
- `@types/uuid`: uuid类型定义
## 测试状态
**编译测试**: 项目成功编译无TypeScript错误
**类型检查**: 所有类型定义正确
**依赖安装**: 必要依赖包已安装
**运行时测试**: 需要在实际环境中测试
**迁移测试**: 需要使用真实数据测试迁移
## 下一步计划
### 短期目标
1. 在开发环境中测试DAO层功能
2. 完善错误处理和边界情况
3. 添加更多单元测试
4. 性能优化和监控
### 中期目标
1. 集成到现有业务逻辑中
2. 提供Web界面的DAO层管理
3. 添加数据备份和恢复功能
4. 实现配置版本控制
### 长期目标
1. 实现数据库后端支持
2. 添加分布式配置管理
3. 实现实时配置同步
4. 支持配置审计和日志
## 优势总结
通过引入DAO层MCPHub获得了以下优势
1. **🏗️ 架构清晰**: 数据访问逻辑与业务逻辑分离
2. **🔄 易于扩展**: 为未来数据库支持做好准备
3. **🧪 便于测试**: 接口可以轻松模拟和单元测试
4. **🔒 类型安全**: 完整的TypeScript类型支持
5. **⚡ 性能优化**: 内置缓存和批量操作
6. **🛡️ 数据完整性**: 强制数据验证和约束
7. **📦 模块化**: 每种数据类型独立管理
8. **🔧 可维护性**: 代码结构清晰,易于维护
这个DAO层的实现为MCPHub项目提供了坚实的数据管理基础支持项目的长期发展和扩展需求。

254
docs/dao-layer.md Normal file
View File

@@ -0,0 +1,254 @@
# MCPHub DAO Layer 设计文档
## 概述
MCPHub的数据访问对象(DAO)层为项目中`mcp_settings.json`文件中的不同数据类型提供了统一的增删改查操作接口。这个设计使得未来从JSON文件存储切换到数据库存储变得更加容易。
## 架构设计
### 核心组件
```
src/dao/
├── base/
│ ├── BaseDao.ts # 基础DAO接口和抽象实现
│ └── JsonFileBaseDao.ts # JSON文件操作的基础类
├── UserDao.ts # 用户数据访问对象
├── ServerDao.ts # 服务器配置数据访问对象
├── GroupDao.ts # 群组数据访问对象
├── SystemConfigDao.ts # 系统配置数据访问对象
├── UserConfigDao.ts # 用户配置数据访问对象
├── DaoFactory.ts # DAO工厂类
├── examples.ts # 使用示例
└── index.ts # 统一导出
```
### 数据类型映射
| 数据类型 | 原始位置 | DAO类 | 主要功能 |
|---------|---------|-------|---------|
| IUser | `settings.users[]` | UserDao | 用户管理、密码验证、权限控制 |
| ServerConfig | `settings.mcpServers{}` | ServerDao | 服务器配置、启用/禁用、工具管理 |
| IGroup | `settings.groups[]` | GroupDao | 群组管理、服务器分组、成员管理 |
| SystemConfig | `settings.systemConfig` | SystemConfigDao | 系统级配置、路由设置、安装配置 |
| UserConfig | `settings.userConfigs{}` | UserConfigDao | 用户个人配置 |
## 主要特性
### 1. 统一的CRUD接口
所有DAO都实现了基础的CRUD操作
```typescript
interface BaseDao<T, K = string> {
findAll(): Promise<T[]>;
findById(id: K): Promise<T | null>;
create(entity: Omit<T, 'id'>): Promise<T>;
update(id: K, entity: Partial<T>): Promise<T | null>;
delete(id: K): Promise<boolean>;
exists(id: K): Promise<boolean>;
count(): Promise<number>;
}
```
### 2. 特定业务操作
每个DAO还提供了针对其数据类型的特定操作
#### UserDao 特殊功能
- `createWithHashedPassword()` - 创建用户时自动哈希密码
- `validateCredentials()` - 验证用户凭据
- `updatePassword()` - 更新用户密码
- `findAdmins()` - 查找管理员用户
#### ServerDao 特殊功能
- `findByOwner()` - 按所有者查找服务器
- `findEnabled()` - 查找启用的服务器
- `findByType()` - 按类型查找服务器
- `setEnabled()` - 启用/禁用服务器
- `updateTools()` - 更新服务器工具配置
#### GroupDao 特殊功能
- `findByOwner()` - 按所有者查找群组
- `findByServer()` - 查找包含特定服务器的群组
- `addServerToGroup()` - 向群组添加服务器
- `removeServerFromGroup()` - 从群组移除服务器
- `findByName()` - 按名称查找群组
### 3. 配置管理特殊功能
#### SystemConfigDao
- `getSection()` - 获取特定配置段
- `updateSection()` - 更新特定配置段
- `reset()` - 重置为默认配置
#### UserConfigDao
- `getSection()` - 获取用户特定配置段
- `updateSection()` - 更新用户特定配置段
- `getAll()` - 获取所有用户配置
## 使用方法
### 1. 基本使用
```typescript
import { getUserDao, getServerDao, getGroupDao } from './dao/index.js';
// 用户操作
const userDao = getUserDao();
const newUser = await userDao.createWithHashedPassword('username', 'password', false);
const user = await userDao.findByUsername('username');
const isValid = await userDao.validateCredentials('username', 'password');
// 服务器操作
const serverDao = getServerDao();
const server = await serverDao.create({
name: 'my-server',
command: 'node',
args: ['server.js'],
enabled: true
});
// 群组操作
const groupDao = getGroupDao();
const group = await groupDao.create({
name: 'my-group',
description: 'Test group',
servers: ['my-server']
});
```
### 2. 配置服务集成
```typescript
import { DaoConfigService, createDaoConfigService } from './config/DaoConfigService.js';
const daoService = createDaoConfigService();
// 加载完整配置
const settings = await daoService.loadSettings();
// 保存配置
await daoService.saveSettings(updatedSettings);
```
### 3. 迁移管理
```typescript
import { migrateToDao, switchToDao, switchToLegacy } from './config/configManager.js';
// 迁移到DAO层
const success = await migrateToDao();
// 运行时切换
switchToDao(); // 切换到DAO层
switchToLegacy(); // 切换回传统方式
```
## 配置选项
可以通过环境变量控制使用哪种数据访问方式:
```bash
# 使用DAO层 (推荐)
USE_DAO_LAYER=true
# 使用传统文件方式 (默认,向后兼容)
USE_DAO_LAYER=false
```
## 未来扩展
### 数据库支持
DAO层的设计使得切换到数据库变得容易只需要
1. 实现新的DAO实现类如DatabaseUserDao
2. 创建新的DaoFactory
3. 更新配置以使用新的工厂
```typescript
// 未来的数据库实现示例
class DatabaseUserDao implements UserDao {
constructor(private db: Database) {}
async findAll(): Promise<IUser[]> {
return this.db.query('SELECT * FROM users');
}
// ... 其他方法
}
```
### 新数据类型
添加新数据类型只需要:
1. 定义数据接口
2. 创建对应的DAO接口和实现
3. 更新DaoFactory
4. 更新配置服务
## 迁移指南
### 从传统方式迁移到DAO层
1. **备份数据**
```bash
cp mcp_settings.json mcp_settings.json.backup
```
2. **运行迁移**
```typescript
import { performMigration } from './config/migrationUtils.js';
await performMigration();
```
3. **验证迁移**
```typescript
import { validateMigration } from './config/migrationUtils.js';
const isValid = await validateMigration();
```
4. **切换到DAO层**
```bash
export USE_DAO_LAYER=true
```
### 性能对比
可以使用内置工具对比性能:
```typescript
import { performanceComparison } from './config/migrationUtils.js';
await performanceComparison();
```
## 最佳实践
1. **类型安全**: 始终使用TypeScript接口确保类型安全
2. **错误处理**: 在DAO操作周围实现适当的错误处理
3. **事务**: 对于复杂操作,考虑使用事务(未来数据库实现)
4. **缓存**: DAO层包含内置缓存机制
5. **测试**: 使用DAO接口进行单元测试的模拟
## 示例代码
查看以下文件获取完整示例:
- `src/dao/examples.ts` - 基本DAO操作示例
- `src/config/migrationUtils.ts` - 迁移和验证工具
- `src/scripts/dao-demo.ts` - 交互式演示脚本
## 总结
DAO层为MCPHub提供了
- 🏗️ **模块化设计**: 每种数据类型都有专门的访问层
- 🔄 **易于迁移**: 为未来切换到数据库做好准备
- 🧪 **可测试性**: 接口可以轻松模拟和测试
- 🔒 **类型安全**: 完整的TypeScript类型支持
-**性能优化**: 内置缓存和批量操作支持
- 🛡️ **数据完整性**: 强制数据验证和约束
通过引入DAO层MCPHub的数据管理变得更加结构化、可维护和可扩展。

107
docs/development.mdx Normal file
View File

@@ -0,0 +1,107 @@
---
title: 'Development'
description: 'Preview changes locally to update your docs'
---
<Info>
**Prerequisite**: Please install Node.js (version 19 or higher) before proceeding. <br />
Please upgrade to ```docs.json``` before proceeding and delete the legacy ```mint.json``` file.
</Info>
Follow these steps to install and run Mintlify on your operating system:
**Step 1**: Install Mintlify:
<CodeGroup>
```bash npm
npm i -g mintlify
```
```bash yarn
yarn global add mintlify
```
</CodeGroup>
**Step 2**: Navigate to the docs directory (where the `docs.json` file is located) and execute the following command:
```bash
mintlify dev
```
A local preview of your documentation will be available at `http://localhost:3000`.
### Custom Ports
By default, Mintlify uses port 3000. You can customize the port Mintlify runs on by using the `--port` flag. To run Mintlify on port 3333, for instance, use this command:
```bash
mintlify dev --port 3333
```
If you attempt to run Mintlify on a port that's already in use, it will use the next available port:
```md
Port 3000 is already in use. Trying 3001 instead.
```
## Mintlify Versions
Please note that each CLI release is associated with a specific version of Mintlify. If your local website doesn't align with the production version, please update the CLI:
<CodeGroup>
```bash npm
npm i -g mintlify@latest
```
```bash yarn
yarn global upgrade mintlify
```
</CodeGroup>
## Validating Links
The CLI can assist with validating reference links made in your documentation. To identify any broken links, use the following command:
```bash
mintlify broken-links
```
## Deployment
<Tip>
Unlimited editors available under the [Pro
Plan](https://mintlify.com/pricing) and above.
</Tip>
If the deployment is successful, you should see the following:
<Frame>
<img src="/images/checks-passed.png" style={{ borderRadius: '0.5rem' }} />
</Frame>
## Code Formatting
We suggest using extensions on your IDE to recognize and format MDX. If you're a VSCode user, consider the [MDX VSCode extension](https://marketplace.visualstudio.com/items?itemName=unifiedjs.vscode-mdx) for syntax highlighting, and [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) for code formatting.
## Troubleshooting
<AccordionGroup>
<Accordion title='Error: Could not load the "sharp" module using the darwin-arm64 runtime'>
This may be due to an outdated version of node. Try the following:
1. Remove the currently-installed version of mintlify: `npm remove -g mintlify`
2. Upgrade to Node v19 or higher.
3. Reinstall mintlify: `npm install -g mintlify`
</Accordion>
<Accordion title="Issue: Encountering an unknown error">
Solution: Go to the root of your device and delete the \~/.mintlify folder. Afterwards, run `mintlify dev` again.
</Accordion>
</AccordionGroup>
Curious about what changed in the CLI version? [Check out the CLI changelog.](https://www.npmjs.com/package/mintlify?activeTab=versions)

View File

@@ -0,0 +1,724 @@
---
title: 'Architecture Overview'
description: "Understand MCPHub's system architecture and design principles"
---
## System Overview
MCPHub is designed as a scalable, modular platform for managing Model Context Protocol (MCP) servers. The architecture follows modern web application patterns with clear separation of concerns, microservices-ready design, and extensibility in mind.
## High-Level Architecture
```mermaid
graph TB
subgraph "Client Layer"
WEB[Web Dashboard]
API[External APIs]
CLI[CLI Tools]
end
subgraph "Application Layer"
LB[Load Balancer/Nginx]
APP[MCPHub Server]
WS[WebSocket Server]
end
subgraph "Service Layer"
MCP[MCP Service]
AUTH[Auth Service]
ROUTE[Smart Routing]
MON[Monitoring Service]
end
subgraph "Data Layer"
PG[(PostgreSQL)]
REDIS[(Redis)]
VECTOR[(Vector Store)]
end
subgraph "MCP Servers"
GITHUB[GitHub MCP]
FS[Filesystem MCP]
DB[Database MCP]
CUSTOM[Custom MCP]
end
WEB --> LB
API --> LB
CLI --> LB
LB --> APP
APP --> WS
APP --> MCP
APP --> AUTH
APP --> ROUTE
APP --> MON
MCP --> GITHUB
MCP --> FS
MCP --> DB
MCP --> CUSTOM
AUTH --> PG
AUTH --> REDIS
ROUTE --> VECTOR
MON --> PG
MON --> REDIS
```
## Core Components
### 1. Application Server
The main Node.js/Express application that handles all HTTP requests and coordinates between services.
```typescript
// src/server.ts - Main application entry point
class MCPHubServer {
private app: Express;
private httpServer: Server;
private wsServer: WebSocketServer;
async start(): Promise<void> {
await this.initializeDatabase();
await this.initializeServices();
await this.setupRoutes();
await this.startServer();
}
}
```
**Key Responsibilities:**
- HTTP request handling
- WebSocket connections for real-time features
- Service coordination
- Middleware chain management
- Error handling and logging
### 2. MCP Service Layer
Manages the lifecycle and communication with MCP servers.
```typescript
// src/services/mcpService.ts
class MCPService {
private servers: Map<string, MCPServerInstance> = new Map();
private processManager: ProcessManager;
async startServer(config: MCPServerConfig): Promise<void> {
const instance = await this.processManager.spawn(config);
this.servers.set(config.name, instance);
await this.waitForHealthy(instance);
}
async executeRequest(serverName: string, request: MCPRequest): Promise<MCPResponse> {
const server = this.servers.get(serverName);
return await server.sendRequest(request);
}
}
```
**Key Features:**
- Process lifecycle management
- Health monitoring
- Request routing
- Error recovery
- Resource management
### 3. Smart Routing Engine
Provides AI-powered tool discovery and routing using vector embeddings.
```typescript
// src/services/smartRouting.ts
class SmartRoutingService {
private vectorStore: VectorStore;
private embeddingService: EmbeddingService;
async findRelevantTools(query: string): Promise<ToolMatch[]> {
const queryEmbedding = await this.embeddingService.embed(query);
const matches = await this.vectorStore.similaritySearch(queryEmbedding);
return this.rankResults(matches, query);
}
async indexTool(tool: ToolDefinition): Promise<void> {
const embedding = await this.embeddingService.embed(tool.description);
await this.vectorStore.upsert(tool.id, embedding, tool);
}
}
```
**Components:**
- Vector embedding generation
- Similarity search
- Result ranking and filtering
- Tool metadata management
### 4. Authentication & Authorization
Handles user authentication, session management, and access control.
```typescript
// src/services/authService.ts
class AuthService {
async authenticate(credentials: Credentials): Promise<User> {
const user = await this.validateCredentials(credentials);
const token = await this.generateJWT(user);
await this.createSession(user, token);
return user;
}
async authorize(user: User, resource: string, action: string): Promise<boolean> {
const permissions = await this.getUserPermissions(user);
return this.checkPermission(permissions, resource, action);
}
}
```
**Features:**
- JWT-based authentication
- Role-based access control (RBAC)
- Session management
- API key authentication
- Group-based permissions
### 5. Monitoring & Logging
Provides comprehensive monitoring, metrics collection, and logging.
```typescript
// src/services/monitoringService.ts
class MonitoringService {
private metricsCollector: MetricsCollector;
private alertManager: AlertManager;
async collectMetrics(): Promise<void> {
const systemMetrics = await this.getSystemMetrics();
const serverMetrics = await this.getMCPServerMetrics();
await this.metricsCollector.record(systemMetrics, serverMetrics);
await this.checkAlerts(systemMetrics, serverMetrics);
}
}
```
**Capabilities:**
- Real-time metrics collection
- Performance monitoring
- Error tracking
- Alert management
- Audit logging
## Data Architecture
### Database Schema
```sql
-- Core entities
CREATE TABLE users (
id UUID PRIMARY KEY,
username VARCHAR UNIQUE NOT NULL,
email VARCHAR UNIQUE NOT NULL,
password_hash VARCHAR NOT NULL,
role VARCHAR NOT NULL DEFAULT 'user',
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE servers (
id UUID PRIMARY KEY,
name VARCHAR UNIQUE NOT NULL,
command VARCHAR NOT NULL,
args JSONB NOT NULL DEFAULT '[]',
env JSONB DEFAULT '{}',
group_name VARCHAR,
status VARCHAR DEFAULT 'stopped',
config JSONB DEFAULT '{}',
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE groups (
id UUID PRIMARY KEY,
name VARCHAR UNIQUE NOT NULL,
description TEXT,
config JSONB DEFAULT '{}',
created_at TIMESTAMP DEFAULT NOW()
);
-- Vector search for smart routing
CREATE TABLE tool_embeddings (
id UUID PRIMARY KEY,
server_name VARCHAR NOT NULL,
tool_name VARCHAR NOT NULL,
description TEXT,
embedding vector(1536),
metadata JSONB DEFAULT '{}',
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Monitoring and logging
CREATE TABLE request_logs (
id UUID PRIMARY KEY,
user_id UUID REFERENCES users(id),
server_name VARCHAR NOT NULL,
tool_name VARCHAR,
request_data JSONB,
response_data JSONB,
status VARCHAR NOT NULL,
duration_ms INTEGER,
created_at TIMESTAMP DEFAULT NOW()
);
```
### Caching Strategy
```typescript
// src/services/cacheService.ts
class CacheService {
// Multi-layer caching strategy
private memoryCache: Map<string, CacheEntry> = new Map();
private redisCache: Redis;
async get<T>(key: string): Promise<T | null> {
// L1: Memory cache
const memoryEntry = this.memoryCache.get(key);
if (memoryEntry && !this.isExpired(memoryEntry)) {
return memoryEntry.value;
}
// L2: Redis cache
const redisValue = await this.redisCache.get(key);
if (redisValue) {
const value = JSON.parse(redisValue);
this.memoryCache.set(key, { value, expiry: Date.now() + 60000 });
return value;
}
return null;
}
}
```
**Cache Layers:**
- **L1 (Memory)**: Fast access for frequently used data
- **L2 (Redis)**: Shared cache across instances
- **L3 (Database)**: Persistent storage with query optimization
## Communication Patterns
### Request Flow
```mermaid
sequenceDiagram
participant Client
participant API
participant Auth
participant Router
participant MCP
participant Server
Client->>API: HTTP Request
API->>Auth: Validate Token
Auth-->>API: User Context
API->>Router: Route Request
Router->>Router: Find Target Server
Router->>MCP: Execute Request
MCP->>Server: MCP Protocol
Server-->>MCP: MCP Response
MCP-->>Router: Formatted Response
Router-->>API: Response Data
API-->>Client: HTTP Response
```
### WebSocket Communication
```typescript
// src/services/websocketService.ts
class WebSocketService {
private connections: Map<string, WebSocket> = new Map();
handleConnection(ws: WebSocket, userId: string): void {
this.connections.set(userId, ws);
ws.on('message', async (data) => {
const message = JSON.parse(data.toString());
await this.handleMessage(userId, message);
});
ws.on('close', () => {
this.connections.delete(userId);
});
}
broadcast(event: string, data: any): void {
this.connections.forEach((ws) => {
ws.send(JSON.stringify({ event, data }));
});
}
}
```
### Event-Driven Architecture
```typescript
// src/events/eventBus.ts
class EventBus {
private listeners: Map<string, EventListener[]> = new Map();
emit(event: string, data: any): void {
const handlers = this.listeners.get(event) || [];
handlers.forEach((handler) => handler(data));
}
on(event: string, handler: EventListener): void {
const handlers = this.listeners.get(event) || [];
handlers.push(handler);
this.listeners.set(event, handlers);
}
}
// Usage
eventBus.on('server.started', (data) => {
logger.info(`Server ${data.name} started`);
monitoringService.updateServerStatus(data.name, 'running');
});
```
## Security Architecture
### Authentication Flow
```mermaid
graph LR
A[Client] --> B[Login Request]
B --> C[Validate Credentials]
C --> D[Generate JWT]
D --> E[Create Session]
E --> F[Return Token]
F --> G[Store in Cookie/Header]
G --> H[Subsequent Requests]
H --> I[Validate Token]
I --> J[Check Permissions]
J --> K[Allow/Deny Access]
```
### Authorization Model
```typescript
// Role-Based Access Control (RBAC)
interface Permission {
resource: string; // e.g., 'servers', 'groups', 'users'
action: string; // e.g., 'create', 'read', 'update', 'delete'
scope?: string; // e.g., 'own', 'group', 'all'
}
interface Role {
name: string;
permissions: Permission[];
}
const roles: Role[] = [
{
name: 'admin',
permissions: [{ resource: '*', action: '*', scope: 'all' }],
},
{
name: 'manager',
permissions: [
{ resource: 'servers', action: '*', scope: 'group' },
{ resource: 'groups', action: 'read', scope: 'all' },
],
},
{
name: 'user',
permissions: [
{ resource: 'servers', action: 'read', scope: 'group' },
{ resource: 'tools', action: 'execute', scope: 'group' },
],
},
];
```
## Scalability Considerations
### Horizontal Scaling
```yaml
# Kubernetes deployment for scaling
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcphub
spec:
replicas: 3
selector:
matchLabels:
app: mcphub
template:
spec:
containers:
- name: mcphub
image: mcphub:latest
resources:
requests:
memory: '256Mi'
cpu: '200m'
limits:
memory: '512Mi'
cpu: '500m'
```
### Load Balancing Strategy
```typescript
// src/services/loadBalancer.ts
class LoadBalancer {
private servers: ServerInstance[] = [];
private algorithm: 'round-robin' | 'least-connections' | 'weighted';
selectServer(): ServerInstance {
switch (this.algorithm) {
case 'round-robin':
return this.roundRobin();
case 'least-connections':
return this.leastConnections();
case 'weighted':
return this.weighted();
}
}
}
```
### Database Scaling
```typescript
// Database connection management
class DatabaseManager {
private readPool: Pool; // Read replicas
private writePool: Pool; // Primary database
async query(sql: string, params: any[]): Promise<any> {
if (this.isReadOperation(sql)) {
return this.readPool.query(sql, params);
} else {
return this.writePool.query(sql, params);
}
}
}
```
## Performance Optimization
### Query Optimization
```sql
-- Optimized queries with proper indexing
CREATE INDEX CONCURRENTLY idx_servers_status_group
ON servers(status, group_name)
WHERE status IN ('running', 'starting');
CREATE INDEX CONCURRENTLY idx_tool_embeddings_similarity
ON tool_embeddings USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
CREATE INDEX CONCURRENTLY idx_request_logs_performance
ON request_logs(created_at, status, duration_ms)
WHERE created_at > NOW() - INTERVAL '30 days';
```
### Caching Strategy
```typescript
// Multi-level caching
class CacheManager {
// Cache server configurations
@Cache({ ttl: 300, key: 'server-config' })
async getServerConfig(name: string): Promise<ServerConfig> {
return this.database.getServerConfig(name);
}
// Cache tool metadata for smart routing
@Cache({ ttl: 3600, key: 'tool-metadata' })
async getToolMetadata(): Promise<ToolMetadata[]> {
return this.database.getToolMetadata();
}
// Cache user permissions
@Cache({ ttl: 600, key: 'user-permissions' })
async getUserPermissions(userId: string): Promise<Permission[]> {
return this.authService.getUserPermissions(userId);
}
}
```
## Monitoring & Observability
### Metrics Collection
```typescript
// src/services/metricsService.ts
class MetricsService {
private prometheus: PrometheusRegistry;
constructor() {
this.initializeMetrics();
}
private initializeMetrics(): void {
// Request metrics
this.requestCount = new Counter({
name: 'mcphub_requests_total',
help: 'Total number of requests',
labelNames: ['method', 'route', 'status'],
});
// Server metrics
this.serverStatus = new Gauge({
name: 'mcphub_server_status',
help: 'Status of MCP servers',
labelNames: ['server_name', 'status'],
});
// Performance metrics
this.responseTime = new Histogram({
name: 'mcphub_response_time_seconds',
help: 'Response time in seconds',
labelNames: ['route'],
});
}
}
```
### Distributed Tracing
```typescript
// OpenTelemetry integration
import { trace } from '@opentelemetry/api';
class MCPService {
async executeRequest(serverName: string, request: MCPRequest): Promise<MCPResponse> {
const span = trace.getActiveSpan();
span?.setAttributes({
'mcp.server': serverName,
'mcp.tool': request.tool,
'mcp.request_id': request.id,
});
try {
const response = await this.sendRequest(serverName, request);
span?.setStatus({ code: SpanStatusCode.OK });
return response;
} catch (error) {
span?.setStatus({
code: SpanStatusCode.ERROR,
message: error.message,
});
throw error;
}
}
}
```
## Extension Points
### Plugin Architecture
```typescript
// Plugin interface
interface MCPHubPlugin {
name: string;
version: string;
init(context: PluginContext): Promise<void>;
destroy(): Promise<void>;
}
// Plugin manager
class PluginManager {
private plugins: Map<string, MCPHubPlugin> = new Map();
async loadPlugin(plugin: MCPHubPlugin): Promise<void> {
await plugin.init(this.createContext());
this.plugins.set(plugin.name, plugin);
}
private createContext(): PluginContext {
return {
eventBus: this.eventBus,
logger: this.logger,
database: this.database,
// ... other services
};
}
}
```
### Custom Middleware
```typescript
// Custom middleware registration
class MiddlewareManager {
register(middleware: Middleware): void {
this.app.use(middleware);
}
registerRoute(path: string, middleware: Middleware): void {
this.app.use(path, middleware);
}
}
// Example custom middleware
const customAuthMiddleware: Middleware = (req, res, next) => {
// Custom authentication logic
next();
};
```
## Deployment Architecture
### Container Strategy
```dockerfile
# Multi-stage build for optimized images
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:18-alpine AS runtime
RUN addgroup -g 1001 -S nodejs
RUN adduser -S mcphub -u 1001
WORKDIR /app
COPY --from=builder --chown=mcphub:nodejs /app .
USER mcphub
EXPOSE 3000
CMD ["node", "dist/server.js"]
```
### Infrastructure as Code
```terraform
# Terraform configuration for AWS deployment
resource "aws_ecs_cluster" "mcphub" {
name = "mcphub-cluster"
}
resource "aws_ecs_service" "mcphub" {
name = "mcphub"
cluster = aws_ecs_cluster.mcphub.id
task_definition = aws_ecs_task_definition.mcphub.arn
desired_count = 3
load_balancer {
target_group_arn = aws_lb_target_group.mcphub.arn
container_name = "mcphub"
container_port = 3000
}
}
```
This architecture provides a solid foundation for building a scalable, maintainable, and extensible MCP server management platform while following modern software development best practices.

View File

@@ -0,0 +1,597 @@
---
title: 'Contributing to MCPHub'
description: 'Learn how to contribute to the MCPHub project'
---
## Welcome Contributors! 🎉
Thank you for your interest in contributing to MCPHub! This guide will help you get started with contributing to the project, whether you're fixing bugs, adding features, improving documentation, or helping with testing.
## Quick Start
1. **Fork the repository** on GitHub
2. **Clone your fork** locally
3. **Create a branch** for your changes
4. **Make your changes** following our guidelines
5. **Test your changes** thoroughly
6. **Submit a pull request**
## Ways to Contribute
### 🐛 Bug Reports
Help us improve MCPHub by reporting bugs:
- **Search existing issues** first to avoid duplicates
- **Use the bug report template** when creating issues
- **Provide detailed information** including steps to reproduce
- **Include system information** (OS, Node.js version, etc.)
```markdown
## Bug Report Template
**Description**
A clear description of what the bug is.
**Steps to Reproduce**
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected Behavior**
What you expected to happen.
**Actual Behavior**
What actually happened.
**Environment**
- OS: [e.g. macOS 12.0]
- Node.js: [e.g. 18.17.0]
- MCPHub Version: [e.g. 1.2.3]
- Browser: [e.g. Chrome 91.0]
**Additional Context**
Any other context about the problem.
```
### ✨ Feature Requests
We welcome feature suggestions:
- **Check existing feature requests** to avoid duplicates
- **Use the feature request template**
- **Explain the use case** and why it would be valuable
- **Consider implementation complexity**
### 🔧 Code Contributions
Ready to write some code? Here's how:
#### Setting Up Development Environment
```bash
# 1. Fork and clone the repository
git clone https://github.com/YOUR_USERNAME/mcphub.git
cd mcphub
# 2. Add upstream remote
git remote add upstream https://github.com/samanhappy/mcphub.git
# 3. Install dependencies
pnpm install
# 4. Set up environment
cp .env.example .env.development
# 5. Start development environment
docker-compose -f docker-compose.dev.yml up -d
pnpm run migrate
pnpm run seed
# 6. Start development server
pnpm run dev
```
#### Branch Naming Convention
Use descriptive branch names with prefixes:
```bash
# Features
git checkout -b feature/smart-routing-improvements
git checkout -b feature/user-authentication
# Bug fixes
git checkout -b fix/server-startup-error
git checkout -b fix/memory-leak-in-cache
# Documentation
git checkout -b docs/api-reference-update
git checkout -b docs/deployment-guide
# Refactoring
git checkout -b refactor/auth-service-cleanup
git checkout -b refactor/database-queries
```
### 📚 Documentation
Help improve our documentation:
- **Fix typos and grammar**
- **Improve existing guides**
- **Add missing documentation**
- **Create tutorials and examples**
- **Translate documentation**
## Development Guidelines
### Code Style
We use ESLint and Prettier to maintain code quality:
```bash
# Check code style
pnpm run lint
# Fix automatically fixable issues
pnpm run lint:fix
# Format code
pnpm run format
# Type check
pnpm run type-check
```
#### TypeScript Best Practices
```typescript
// ✅ Good: Use proper types
interface MCPServerConfig {
name: string;
command: string;
args: string[];
env?: Record<string, string>;
}
// ✅ Good: Use async/await
async function startServer(config: MCPServerConfig): Promise<void> {
try {
await mcpService.start(config);
} catch (error) {
logger.error('Failed to start server', { error, config });
throw error;
}
}
// ❌ Bad: Using any type
function processData(data: any): any {
return data.something();
}
// ❌ Bad: Not handling errors
async function riskyOperation(): Promise<void> {
await dangerousFunction(); // Could throw
}
```
#### React/Frontend Guidelines
```tsx
// ✅ Good: Functional components with proper typing
interface ServerCardProps {
server: MCPServer;
onStart: (serverId: string) => void;
onStop: (serverId: string) => void;
}
const ServerCard: React.FC<ServerCardProps> = ({ server, onStart, onStop }) => {
const handleStart = useCallback(() => {
onStart(server.id);
}, [server.id, onStart]);
return (
<Card data-testid={`server-card-${server.id}`}>
<CardHeader>
<CardTitle>{server.name}</CardTitle>
<Badge variant={server.status === 'running' ? 'success' : 'secondary'}>
{server.status}
</Badge>
</CardHeader>
<CardContent>
<p>{server.description}</p>
</CardContent>
<CardActions>
{server.status === 'stopped' ? (
<Button onClick={handleStart}>Start</Button>
) : (
<Button onClick={() => onStop(server.id)}>Stop</Button>
)}
</CardActions>
</Card>
);
};
```
### Testing Requirements
All contributions must include appropriate tests:
#### Unit Tests
```typescript
// src/services/__tests__/mcpService.test.ts
import { MCPService } from '../mcpService';
import { mockLogger, mockDatabase } from '../../__mocks__';
describe('MCPService', () => {
let service: MCPService;
beforeEach(() => {
service = new MCPService(mockLogger, mockDatabase);
});
describe('startServer', () => {
it('should start a server successfully', async () => {
const config = {
name: 'test-server',
command: 'node',
args: ['server.js'],
};
await service.startServer(config);
expect(service.getServerStatus('test-server')).toBe('running');
});
it('should handle server startup failures', async () => {
const invalidConfig = {
name: 'invalid-server',
command: 'invalid-command',
args: [],
};
await expect(service.startServer(invalidConfig)).rejects.toThrow(
'Failed to start server: Command not found',
);
});
});
});
```
#### Integration Tests
```typescript
// src/__tests__/integration/server-api.test.ts
import request from 'supertest';
import { app } from '../../app';
import { setupTestDatabase, teardownTestDatabase } from '../helpers/database';
describe('Server API Integration', () => {
beforeAll(async () => {
await setupTestDatabase();
});
afterAll(async () => {
await teardownTestDatabase();
});
describe('POST /api/servers', () => {
it('should create a new server', async () => {
const serverData = {
name: 'test-server',
command: 'node',
args: ['server.js'],
group: 'development',
};
const response = await request(app).post('/api/servers').send(serverData).expect(201);
expect(response.body).toMatchObject({
name: 'test-server',
status: 'stopped',
group: 'development',
});
});
});
});
```
#### End-to-End Tests
```typescript
// tests/e2e/server-management.spec.ts
import { test, expect } from '@playwright/test';
test.describe('Server Management', () => {
test('should create and manage MCP servers', async ({ page }) => {
await page.goto('/dashboard');
// Create new server
await page.click('[data-testid="add-server-button"]');
await page.fill('[data-testid="server-name-input"]', 'test-server');
await page.fill('[data-testid="server-command-input"]', 'node server.js');
await page.click('[data-testid="save-server-button"]');
// Verify server appears in list
await expect(page.locator('[data-testid="server-list"]')).toContainText('test-server');
// Start the server
await page.click('[data-testid="start-server-test-server"]');
// Verify server is running
await expect(page.locator('[data-testid="server-status-test-server"]')).toContainText(
'running',
);
});
});
```
### Commit Guidelines
We follow [Conventional Commits](https://www.conventionalcommits.org/):
```bash
# Format: <type>[optional scope]: <description>
# Features
git commit -m "feat(auth): add JWT token refresh functionality"
git commit -m "feat(ui): implement server status dashboard"
# Bug fixes
git commit -m "fix(api): resolve memory leak in server manager"
git commit -m "fix(db): handle connection timeout gracefully"
# Documentation
git commit -m "docs(api): add examples for server endpoints"
git commit -m "docs(readme): update installation instructions"
# Refactoring
git commit -m "refactor(services): extract auth logic into separate module"
# Tests
git commit -m "test(api): add integration tests for server management"
# Chores
git commit -m "chore(deps): update dependencies to latest versions"
```
#### Commit Types
- **feat**: New feature
- **fix**: Bug fix
- **docs**: Documentation changes
- **style**: Code style changes (formatting, etc.)
- **refactor**: Code refactoring
- **test**: Adding or updating tests
- **chore**: Maintenance tasks
- **perf**: Performance improvements
- **ci**: CI/CD changes
### Pull Request Process
#### Before Submitting
```bash
# 1. Sync with upstream
git fetch upstream
git checkout main
git merge upstream/main
# 2. Rebase your feature branch
git checkout feature/your-feature
git rebase main
# 3. Run all checks
pnpm run lint
pnpm run type-check
pnpm run test
pnpm run build
# 4. Update documentation if needed
# 5. Add/update tests for your changes
```
#### Pull Request Template
```markdown
## Description
Brief description of the changes and motivation.
## Type of Change
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation update
## Testing
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] E2E tests pass (if applicable)
- [ ] Manual testing completed
## Documentation
- [ ] Code is self-documenting
- [ ] API documentation updated
- [ ] User documentation updated
- [ ] README updated (if needed)
## Checklist
- [ ] My code follows the project's style guidelines
- [ ] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
## Screenshots (if applicable)
Add screenshots to help explain your changes.
## Additional Notes
Any additional information that reviewers should know.
```
### Code Review Process
#### For Contributors
- **Be patient**: Reviews take time, and reviewers may have questions
- **Be responsive**: Address feedback promptly and clearly
- **Be open**: Accept constructive criticism and suggestions
- **Ask questions**: If feedback is unclear, ask for clarification
#### For Reviewers
- **Be constructive**: Provide helpful suggestions, not just criticism
- **Be specific**: Point out exact issues and suggest solutions
- **Be timely**: Review PRs within a reasonable timeframe
- **Be encouraging**: Recognize good work and improvements
## Community Guidelines
### Code of Conduct
We are committed to providing a welcoming and inspiring community for all:
- **Be respectful**: Treat everyone with respect and kindness
- **Be inclusive**: Welcome people of all backgrounds and skill levels
- **Be collaborative**: Work together towards common goals
- **Be patient**: Help others learn and grow
- **Be professional**: Maintain professional communication
### Communication Channels
- **GitHub Issues**: Bug reports and feature requests
- **GitHub Discussions**: General questions and community chat
- **Discord**: Real-time community chat (link in README)
- **Email**: Security issues and private matters
## Getting Help
### Documentation
- [Getting Started Guide](./getting-started.mdx)
- [Architecture Overview](./architecture.mdx)
- [API Reference](../api-reference/introduction.mdx)
- [Configuration Guide](../configuration/mcp-settings.mdx)
### Common Issues
**Build Failures**
```bash
# Clear and reinstall dependencies
rm -rf node_modules pnpm-lock.yaml
pnpm install
# Clear build cache
rm -rf dist/
pnpm run build
```
**Test Failures**
```bash
# Run tests with verbose output
pnpm run test -- --verbose
# Run specific test file
pnpm test src/services/mcpService.test.ts
# Debug tests
pnpm run test:debug
```
**Database Issues**
```bash
# Reset database
pnpm run db:reset
# Run migrations
pnpm run migrate
# Seed development data
pnpm run seed
```
### Getting Support
If you need help:
1. **Check the documentation** first
2. **Search existing issues** on GitHub
3. **Ask in GitHub Discussions** for general questions
4. **Create an issue** if you found a bug
5. **Join our Discord** for real-time help
## Recognition
Contributors will be recognized in several ways:
- **Contributors file**: All contributors are listed in CONTRIBUTORS.md
- **Release notes**: Significant contributions are mentioned in release notes
- **GitHub badges**: Active contributors receive special recognition
- **Community showcase**: Outstanding contributions are featured in our blog
## Advanced Topics
### Maintainer Guidelines
For project maintainers:
#### Release Process
```bash
# 1. Create release branch
git checkout -b release/v1.2.0
# 2. Update version
npm version 1.2.0 --no-git-tag-version
# 3. Update changelog
# Edit CHANGELOG.md
# 4. Commit changes
git add .
git commit -m "chore(release): prepare v1.2.0"
# 5. Create PR for review
# 6. After merge, tag release
git tag v1.2.0
git push origin v1.2.0
```
#### Security Handling
For security issues:
1. **Do not** create public issues
2. **Email** security@mcphub.dev
3. **Wait** for response before disclosure
4. **Coordinate** with maintainers on fixes
### Architectural Decisions
When making significant changes:
1. **Create an RFC** (Request for Comments) issue
2. **Discuss** with the community
3. **Get approval** from maintainers
4. **Document** decisions in ADR (Architecture Decision Records)
## Thank You! 🙏
Thank you for taking the time to contribute to MCPHub! Every contribution, no matter how small, helps make the project better for everyone. We look forward to collaborating with you!

View File

@@ -0,0 +1,244 @@
---
title: 'Getting Started with Development'
description: 'Learn how to set up your development environment for MCPHub'
---
# Getting Started with Development
This guide will help you set up your development environment for contributing to MCPHub.
## Prerequisites
Before you begin, ensure you have the following installed:
- **Node.js** (version 18 or higher)
- **pnpm** (recommended package manager)
- **Git**
- **Docker** (optional, for containerized development)
## Setting Up the Development Environment
### 1. Clone the Repository
```bash
git clone https://github.com/your-username/mcphub.git
cd mcphub
```
### 2. Install Dependencies
```bash
pnpm install
```
### 3. Environment Configuration
Create a `.env` file in the root directory:
```bash
cp .env.example .env
```
Configure the following environment variables:
```env
# Server Configuration
PORT=3000
NODE_ENV=development
# Database Configuration
DATABASE_URL=postgresql://username:password@localhost:5432/mcphub
# JWT Configuration
JWT_SECRET=your-secret-key
JWT_EXPIRES_IN=24h
# OpenAI Configuration (for smart routing)
OPENAI_API_KEY=your-openai-api-key
```
### 4. Database Setup
If using PostgreSQL, create a database:
```bash
createdb mcphub
```
### 5. MCP Server Configuration
Create or modify `mcp_settings.json`:
```json
{
"mcpServers": {
"fetch": {
"command": "uvx",
"args": ["mcp-server-fetch"]
},
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest", "--headless"]
}
}
}
```
## Development Workflow
### Running the Development Server
Start both backend and frontend in development mode:
```bash
pnpm dev
```
This will start:
- Backend server on `http://localhost:3000`
- Frontend development server on `http://localhost:5173`
### Running Backend Only
```bash
pnpm backend:dev
```
### Running Frontend Only
```bash
pnpm frontend:dev
```
### Building the Project
Build both backend and frontend:
```bash
pnpm build
```
## Project Structure
```
mcphub/
├── src/ # Backend source code
│ ├── controllers/ # Express controllers
│ ├── routes/ # API routes
│ ├── services/ # Business logic
│ ├── models/ # Database models
│ └── utils/ # Utility functions
├── frontend/ # Frontend React application
│ ├── src/
│ │ ├── components/ # React components
│ │ ├── pages/ # Page components
│ │ ├── services/ # API services
│ │ └── utils/ # Frontend utilities
├── docs/ # Documentation
├── bin/ # CLI scripts
└── scripts/ # Build and utility scripts
```
## Development Tools
### Linting and Formatting
```bash
# Run ESLint
pnpm lint
# Format code with Prettier
pnpm format
```
### Testing
```bash
# Run tests
pnpm test
# Run tests in watch mode
pnpm test --watch
```
### Debugging
To debug the backend with Node.js inspector:
```bash
pnpm backend:debug
```
Then attach your debugger to `http://localhost:9229`.
## Making Changes
### Backend Development
1. **Controllers**: Handle HTTP requests and responses
2. **Services**: Implement business logic
3. **Models**: Define database schemas
4. **Routes**: Define API endpoints
### Frontend Development
1. **Components**: Reusable React components
2. **Pages**: Route-specific components
3. **Services**: API communication
4. **Hooks**: Custom React hooks
### Adding New MCP Servers
1. Update `mcp_settings.json` with the new server configuration
2. Test the server integration
3. Update documentation if needed
## Common Development Tasks
### Adding a New API Endpoint
1. Create a controller in `src/controllers/`
2. Define the route in `src/routes/`
3. Add any necessary middleware
4. Write tests for the new endpoint
### Adding a New Frontend Feature
1. Create components in `frontend/src/components/`
2. Add routes if needed
3. Implement API integration
4. Style with Tailwind CSS
### Database Migrations
When modifying database schemas:
1. Update models in `src/models/`
2. Create migration scripts if using TypeORM
3. Test migrations locally
## Troubleshooting
### Common Issues
**Port conflicts**: Ensure ports 3000 and 5173 are available
**Database connection**: Verify PostgreSQL is running and credentials are correct
**MCP server startup**: Check server configurations in `mcp_settings.json`
**Permission issues**: Ensure MCP servers have necessary permissions
### Getting Help
- Check the [Contributing Guide](/development/contributing)
- Review [Architecture Documentation](/development/architecture)
- Open an issue on GitHub for bugs
- Join our community discussions
## Next Steps
- Read the [Architecture Overview](/development/architecture)
- Learn about [Contributing Guidelines](/development/contributing)
- Explore [Configuration Options](/configuration/environment-variables)

172
docs/docs.json Normal file
View File

@@ -0,0 +1,172 @@
{
"$schema": "https://mintlify.com/docs.json",
"theme": "mint",
"name": "MCPHub Documentation",
"description": "The Unified Hub for Model Context Protocol (MCP) Servers",
"colors": {
"primary": "#16A34A",
"light": "#07C983",
"dark": "#15803D"
},
"favicon": "/favicon.ico",
"navigation": {
"tabs": [
{
"tab": "English",
"groups": [
{
"group": "Get Started",
"pages": [
"index",
"quickstart",
"installation"
]
},
{
"group": "Core Features",
"pages": [
"features/server-management",
"features/group-management",
"features/smart-routing",
"features/oauth"
]
},
{
"group": "Configuration",
"pages": [
"configuration/mcp-settings",
"configuration/environment-variables",
"configuration/docker-setup",
"configuration/nginx"
]
}
]
},
{
"tab": "中文",
"groups": [
{
"group": "开始使用",
"pages": [
"zh/index",
"zh/quickstart",
"zh/installation"
]
},
{
"group": "核心功能",
"pages": [
"zh/features/server-management",
"zh/features/group-management",
"zh/features/smart-routing",
"zh/features/oauth"
]
},
{
"group": "配置指南",
"pages": [
"zh/configuration/mcp-settings",
"zh/configuration/environment-variables",
"zh/configuration/docker-setup",
"zh/configuration/nginx"
]
}
]
},
{
"tab": "API",
"groups": [
{
"group": "MCP Endpoints",
"pages": [
"api-reference/introduction",
"api-reference/mcp-http",
"api-reference/mcp-sse",
"api-reference/smart-routing"
]
},
{
"group": "OpenAPI Endpoints",
"pages": [
"api-reference/openapi"
]
},
{
"group": "Management Endpoints",
"pages": [
"api-reference/servers",
"api-reference/groups",
"api-reference/users",
"api-reference/tools",
"api-reference/prompts",
"api-reference/auth",
"api-reference/logs",
"api-reference/config",
"api-reference/system"
]
}
]
},
{
"tab": "接口",
"groups": [
{
"group": "MCP 端点",
"pages": [
"zh/api-reference/introduction",
"zh/api-reference/mcp-http",
"zh/api-reference/mcp-sse",
"zh/api-reference/smart-routing"
]
},
{
"group": "OpenAPI 端点",
"pages": [
"zh/api-reference/openapi"
]
},
{
"group": "管理端点",
"pages": [
"zh/api-reference/servers",
"zh/api-reference/groups",
"zh/api-reference/users",
"zh/api-reference/tools",
"zh/api-reference/prompts",
"zh/api-reference/auth",
"zh/api-reference/logs",
"zh/api-reference/config",
"zh/api-reference/system"
]
}
]
}
],
"global": {
"anchors": []
}
},
"logo": {
"light": "/logo/light.svg",
"dark": "/logo/dark.svg"
},
"navbar": {
"links": [
{
"label": "Demo",
"href": "https://demo.mcphubx.com"
}
],
"primary": {
"type": "button",
"label": "Get Started",
"href": "https://docs.mcphubx.com/quickstart"
}
},
"footer": {
"socials": {
"github": "https://github.com/samanhappy/mcphub",
"discord": "https://discord.gg/qMKNsn5Q"
}
}
}

View File

@@ -0,0 +1,267 @@
# Environment Variable Expansion in mcp_settings.json
## Overview
MCPHub now supports comprehensive environment variable expansion throughout the entire `mcp_settings.json` configuration file. This allows you to externalize sensitive information and configuration values, making your setup more secure and flexible.
## Supported Formats
MCPHub supports two environment variable formats:
1. **${VAR}** - Standard format (recommended)
2. **$VAR** - Unix-style format (variable name must start with an uppercase letter or underscore, followed by uppercase letters, numbers, or underscores)
## What Can Be Expanded
Environment variables can now be used in **ANY** string value throughout your configuration:
- Server URLs
- Commands and arguments
- Headers
- Environment variables passed to child processes
- OpenAPI specifications and security configurations
- OAuth credentials
- System configuration values
- Any other string fields
## Examples
### 1. SSE/HTTP Server Configuration
```json
{
"mcpServers": {
"my-api-server": {
"type": "sse",
"url": "${MCP_SERVER_URL}",
"headers": {
"Authorization": "Bearer ${API_TOKEN}",
"X-Custom-Header": "${CUSTOM_VALUE}"
}
}
}
}
```
Environment variables:
```bash
export MCP_SERVER_URL="https://api.example.com/mcp"
export API_TOKEN="secret-token-123"
export CUSTOM_VALUE="my-custom-value"
```
### 2. Stdio Server Configuration
```json
{
"mcpServers": {
"my-python-server": {
"type": "stdio",
"command": "${PYTHON_PATH}",
"args": ["-m", "${MODULE_NAME}", "--api-key", "${API_KEY}"],
"env": {
"DATABASE_URL": "${DATABASE_URL}",
"DEBUG": "${DEBUG_MODE}"
}
}
}
}
```
Environment variables:
```bash
export PYTHON_PATH="/usr/bin/python3"
export MODULE_NAME="my_mcp_server"
export API_KEY="secret-api-key"
export DATABASE_URL="postgresql://localhost/mydb"
export DEBUG_MODE="true"
```
### 3. OpenAPI Server Configuration
```json
{
"mcpServers": {
"openapi-service": {
"type": "openapi",
"openapi": {
"url": "${OPENAPI_SPEC_URL}",
"security": {
"type": "apiKey",
"apiKey": {
"name": "X-API-Key",
"in": "header",
"value": "${OPENAPI_API_KEY}"
}
}
}
}
}
}
```
Environment variables:
```bash
export OPENAPI_SPEC_URL="https://api.example.com/openapi.json"
export OPENAPI_API_KEY="your-api-key-here"
```
### 4. OAuth Configuration
```json
{
"mcpServers": {
"oauth-server": {
"type": "sse",
"url": "${OAUTH_SERVER_URL}",
"oauth": {
"clientId": "${OAUTH_CLIENT_ID}",
"clientSecret": "${OAUTH_CLIENT_SECRET}",
"accessToken": "${OAUTH_ACCESS_TOKEN}"
}
}
}
}
```
Environment variables:
```bash
export OAUTH_SERVER_URL="https://oauth.example.com/mcp"
export OAUTH_CLIENT_ID="my-client-id"
export OAUTH_CLIENT_SECRET="my-client-secret"
export OAUTH_ACCESS_TOKEN="my-access-token"
```
### 5. System Configuration
```json
{
"systemConfig": {
"install": {
"pythonIndexUrl": "${PYTHON_INDEX_URL}",
"npmRegistry": "${NPM_REGISTRY}"
},
"mcpRouter": {
"apiKey": "${MCPROUTER_API_KEY}",
"referer": "${MCPROUTER_REFERER}"
}
}
}
```
Environment variables:
```bash
export PYTHON_INDEX_URL="https://pypi.tuna.tsinghua.edu.cn/simple"
export NPM_REGISTRY="https://registry.npmmirror.com"
export MCPROUTER_API_KEY="router-api-key"
export MCPROUTER_REFERER="https://myapp.com"
```
## Complete Example
See [examples/mcp_settings_with_env_vars.json](../examples/mcp_settings_with_env_vars.json) for a comprehensive example configuration using environment variables.
## Best Practices
### Security
1. **Never commit sensitive values to version control** - Use environment variables for all secrets
2. **Use .env files for local development** - MCPHub automatically loads `.env` files
3. **Use secure secret management in production** - Consider using Docker secrets, Kubernetes secrets, or cloud provider secret managers
### Organization
1. **Group related variables** - Use prefixes for related configuration (e.g., `API_`, `DB_`, `OAUTH_`)
2. **Document required variables** - Maintain a list of required environment variables in your README
3. **Provide example .env file** - Create a `.env.example` file with placeholder values
### Example .env File
```bash
# Server Configuration
MCP_SERVER_URL=https://api.example.com/mcp
API_TOKEN=your-api-token-here
# Python Server
PYTHON_PATH=/usr/bin/python3
MODULE_NAME=my_mcp_server
# Database
DATABASE_URL=postgresql://localhost/mydb
# OpenAPI
OPENAPI_SPEC_URL=https://api.example.com/openapi.json
OPENAPI_API_KEY=your-openapi-key
# OAuth
OAUTH_CLIENT_ID=your-client-id
OAUTH_CLIENT_SECRET=your-client-secret
OAUTH_ACCESS_TOKEN=your-access-token
```
## Docker Usage
When using Docker, pass environment variables using `-e` flag or `--env-file`:
```bash
# Using individual variables
docker run -e API_TOKEN=secret -e SERVER_URL=https://api.example.com mcphub
# Using env file
docker run --env-file .env mcphub
```
Or in docker-compose.yml:
```yaml
version: '3.8'
services:
mcphub:
image: mcphub
env_file:
- .env
environment:
- MCP_SERVER_URL=${MCP_SERVER_URL}
- API_TOKEN=${API_TOKEN}
```
## Troubleshooting
### Variable Not Expanding
If a variable is not expanding:
1. Check that the variable is set: `echo $VAR_NAME`
2. Verify the variable name matches exactly (case-sensitive)
3. Ensure the variable is exported: `export VAR_NAME=value`
4. Restart MCPHub after setting environment variables
### Empty Values
If an environment variable is not set, it will be replaced with an empty string. Make sure all required variables are set before starting MCPHub.
### Nested Variables
Environment variables in nested objects and arrays are fully supported:
```json
{
"nested": {
"deep": {
"value": "${MY_VAR}"
}
},
"array": ["${VAR1}", "${VAR2}"]
}
```
## Migration from Previous Version
If you were previously using environment variables only in headers, no changes are needed. The new implementation is backward compatible and simply extends support to all configuration fields.
## Technical Details
- Environment variables are expanded once when the configuration is loaded
- Expansion is recursive and handles nested objects and arrays
- Non-string values (booleans, numbers, null) are preserved as-is
- Empty string is used when an environment variable is not set

37
docs/essentials/code.mdx Normal file
View File

@@ -0,0 +1,37 @@
---
title: 'Code Blocks'
description: 'Display inline code and code blocks'
icon: 'code'
---
## Basic
### Inline Code
To denote a `word` or `phrase` as code, enclose it in backticks (`).
```
To denote a `word` or `phrase` as code, enclose it in backticks (`).
```
### Code Block
Use [fenced code blocks](https://www.markdownguide.org/extended-syntax/#fenced-code-blocks) by enclosing code in three backticks and follow the leading ticks with the programming language of your snippet to get syntax highlighting. Optionally, you can also write the name of your code after the programming language.
```java HelloWorld.java
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
```
````md
```java HelloWorld.java
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
```
````

View File

@@ -0,0 +1,59 @@
---
title: 'Images and Embeds'
description: 'Add image, video, and other HTML elements'
icon: 'image'
---
<img
style={{ borderRadius: '0.5rem' }}
src="https://mintlify-assets.b-cdn.net/bigbend.jpg"
/>
## Image
### Using Markdown
The [markdown syntax](https://www.markdownguide.org/basic-syntax/#images) lets you add images using the following code
```md
![title](/path/image.jpg)
```
Note that the image file size must be less than 5MB. Otherwise, we recommend hosting on a service like [Cloudinary](https://cloudinary.com/) or [S3](https://aws.amazon.com/s3/). You can then use that URL and embed.
### Using Embeds
To get more customizability with images, you can also use [embeds](/writing-content/embed) to add images
```html
<img height="200" src="/path/image.jpg" />
```
## Embeds and HTML elements
<iframe
width="560"
height="315"
src="https://www.youtube.com/embed/4KzFe50RQkQ"
title="YouTube video player"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
style={{ width: '100%', borderRadius: '0.5rem' }}
></iframe>
<br />
<Tip>
Mintlify supports [HTML tags in Markdown](https://www.markdownguide.org/basic-syntax/#html). This is helpful if you prefer HTML tags to Markdown syntax, and lets you create documentation with infinite flexibility.
</Tip>
### iFrames
Loads another HTML page within the document. Most commonly used for embedding videos.
```html
<iframe src="https://www.youtube.com/embed/4KzFe50RQkQ"> </iframe>
```

View File

@@ -0,0 +1,88 @@
---
title: 'Markdown Syntax'
description: 'Text, title, and styling in standard markdown'
icon: 'text-size'
---
## Titles
Best used for section headers.
```md
## Titles
```
### Subtitles
Best use to subsection headers.
```md
### Subtitles
```
<Tip>
Each **title** and **subtitle** creates an anchor and also shows up on the table of contents on the right.
</Tip>
## Text Formatting
We support most markdown formatting. Simply add `**`, `_`, or `~` around text to format it.
| Style | How to write it | Result |
| ------------- | ----------------- | --------------- |
| Bold | `**bold**` | **bold** |
| Italic | `_italic_` | _italic_ |
| Strikethrough | `~strikethrough~` | ~strikethrough~ |
You can combine these. For example, write `**_bold and italic_**` to get **_bold and italic_** text.
You need to use HTML to write superscript and subscript text. That is, add `<sup>` or `<sub>` around your text.
| Text Size | How to write it | Result |
| ----------- | ------------------------ | ---------------------- |
| Superscript | `<sup>superscript</sup>` | <sup>superscript</sup> |
| Subscript | `<sub>subscript</sub>` | <sub>subscript</sub> |
## Linking to Pages
You can add a link by wrapping text in `[]()`. You would write `[link to google](https://google.com)` to [link to google](https://google.com).
Links to pages in your docs need to be root-relative. Basically, you should include the entire folder path. For example, `[link to text](/writing-content/text)` links to the page "Text" in our components section.
Relative links like `[link to text](../text)` will open slower because we cannot optimize them as easily.
## Blockquotes
### Singleline
To create a blockquote, add a `>` in front of a paragraph.
> Dorothy followed her through many of the beautiful rooms in her castle.
```md
> Dorothy followed her through many of the beautiful rooms in her castle.
```
### Multiline
> Dorothy followed her through many of the beautiful rooms in her castle.
>
> The Witch bade her clean the pots and kettles and sweep the floor and keep the fire fed with wood.
```md
> Dorothy followed her through many of the beautiful rooms in her castle.
>
> The Witch bade her clean the pots and kettles and sweep the floor and keep the fire fed with wood.
```
### LaTeX
Mintlify supports [LaTeX](https://www.latex-project.org) through the Latex component.
<Latex>8 x (vk x H1 - H2) = (0,1)</Latex>
```md
<Latex>8 x (vk x H1 - H2) = (0,1)</Latex>
```

View File

@@ -0,0 +1,87 @@
---
title: 'Navigation'
description: 'The navigation field in docs.json defines the pages that go in the navigation menu'
icon: 'map'
---
The navigation menu is the list of links on every website.
You will likely update `docs.json` every time you add a new page. Pages do not show up automatically.
## Navigation syntax
Our navigation syntax is recursive which means you can make nested navigation groups. You don't need to include `.mdx` in page names.
<CodeGroup>
```json Regular Navigation
"navigation": {
"tabs": [
{
"tab": "Docs",
"groups": [
{
"group": "Getting Started",
"pages": ["quickstart"]
}
]
}
]
}
```
```json Nested Navigation
"navigation": {
"tabs": [
{
"tab": "Docs",
"groups": [
{
"group": "Getting Started",
"pages": [
"quickstart",
{
"group": "Nested Reference Pages",
"pages": ["nested-reference-page"]
}
]
}
]
}
]
}
```
</CodeGroup>
## Folders
Simply put your MDX files in folders and update the paths in `docs.json`.
For example, to have a page at `https://yoursite.com/your-folder/your-page` you would make a folder called `your-folder` containing an MDX file called `your-page.mdx`.
<Warning>
You cannot use `api` for the name of a folder unless you nest it inside another folder. Mintlify uses Next.js which reserves the top-level `api` folder for internal server calls. A folder name such as `api-reference` would be accepted.
</Warning>
```json Navigation With Folder
"navigation": {
"tabs": [
{
"tab": "Docs",
"groups": [
{
"group": "Group Name",
"pages": ["your-folder/your-page"]
}
]
}
]
}
```
## Hidden Pages
MDX files not included in `docs.json` will not show up in the sidebar but are accessible through the search bar and by linking directly to them.

View File

@@ -0,0 +1,110 @@
---
title: Reusable Snippets
description: Reusable, custom snippets to keep content in sync
icon: 'recycle'
---
import SnippetIntro from '/snippets/snippet-intro.mdx';
<SnippetIntro />
## Creating a custom snippet
**Pre-condition**: You must create your snippet file in the `snippets` directory.
<Note>
Any page in the `snippets` directory will be treated as a snippet and will not
be rendered into a standalone page. If you want to create a standalone page
from the snippet, import the snippet into another file and call it as a
component.
</Note>
### Default export
1. Add content to your snippet file that you want to re-use across multiple
locations. Optionally, you can add variables that can be filled in via props
when you import the snippet.
```mdx snippets/my-snippet.mdx
Hello world! This is my content I want to reuse across pages. My keyword of the
day is {word}.
```
<Warning>
The content that you want to reuse must be inside the `snippets` directory in
order for the import to work.
</Warning>
2. Import the snippet into your destination file.
```mdx destination-file.mdx
---
title: My title
description: My Description
---
import MySnippet from '/snippets/path/to/my-snippet.mdx';
## Header
Lorem impsum dolor sit amet.
<MySnippet word="bananas" />
```
### Reusable variables
1. Export a variable from your snippet file:
```mdx snippets/path/to/custom-variables.mdx
export const myName = 'my name';
export const myObject = { fruit: 'strawberries' };
```
2. Import the snippet from your destination file and use the variable:
```mdx destination-file.mdx
---
title: My title
description: My Description
---
import { myName, myObject } from '/snippets/path/to/custom-variables.mdx';
Hello, my name is {myName} and I like {myObject.fruit}.
```
### Reusable components
1. Inside your snippet file, create a component that takes in props by exporting
your component in the form of an arrow function.
```mdx snippets/custom-component.mdx
export const MyComponent = ({ title }) => (
<div>
<h1>{title}</h1>
<p>... snippet content ...</p>
</div>
);
```
<Warning>
MDX does not compile inside the body of an arrow function. Stick to HTML
syntax when you can or use a default export if you need to use MDX.
</Warning>
2. Import the snippet into your destination file and pass in the props
```mdx destination-file.mdx
---
title: My title
description: My Description
---
import { MyComponent } from '/snippets/custom-component.mdx';
Lorem ipsum dolor sit amet.
<MyComponent title={'Custom title'} />
```

View File

@@ -0,0 +1,318 @@
---
title: 'Global Settings'
description: 'Mintlify gives you complete control over the look and feel of your documentation using the docs.json file'
icon: 'gear'
---
Every Mintlify site needs a `docs.json` file with the core configuration settings. Learn more about the [properties](#properties) below.
## Properties
<ResponseField name="name" type="string" required>
Name of your project. Used for the global title.
Example: `mintlify`
</ResponseField>
<ResponseField name="navigation" type="Navigation[]" required>
An array of groups with all the pages within that group
<Expandable title="Navigation">
<ResponseField name="group" type="string">
The name of the group.
Example: `Settings`
</ResponseField>
<ResponseField name="pages" type="string[]">
The relative paths to the markdown files that will serve as pages.
Example: `["customization", "page"]`
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="logo" type="string or object">
Path to logo image or object with path to "light" and "dark" mode logo images
<Expandable title="Logo">
<ResponseField name="light" type="string">
Path to the logo in light mode
</ResponseField>
<ResponseField name="dark" type="string">
Path to the logo in dark mode
</ResponseField>
<ResponseField name="href" type="string" default="/">
Where clicking on the logo links you to
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="favicon" type="string">
Path to the favicon image
</ResponseField>
<ResponseField name="colors" type="Colors">
Hex color codes for your global theme
<Expandable title="Colors">
<ResponseField name="primary" type="string" required>
The primary color. Used for most often for highlighted content, section
headers, accents, in light mode
</ResponseField>
<ResponseField name="light" type="string">
The primary color for dark mode. Used for most often for highlighted
content, section headers, accents, in dark mode
</ResponseField>
<ResponseField name="dark" type="string">
The primary color for important buttons
</ResponseField>
<ResponseField name="background" type="object">
The color of the background in both light and dark mode
<Expandable title="Object">
<ResponseField name="light" type="string" required>
The hex color code of the background in light mode
</ResponseField>
<ResponseField name="dark" type="string" required>
The hex color code of the background in dark mode
</ResponseField>
</Expandable>
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="topbarLinks" type="TopbarLink[]">
Array of `name`s and `url`s of links you want to include in the topbar
<Expandable title="TopbarLink">
<ResponseField name="name" type="string">
The name of the button.
Example: `Contact us`
</ResponseField>
<ResponseField name="url" type="string">
The url once you click on the button. Example: `https://mintlify.com/docs`
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="topbarCtaButton" type="Call to Action">
<Expandable title="Topbar Call to Action">
<ResponseField name="type" type={'"link" or "github"'} default="link">
Link shows a button. GitHub shows the repo information at the url provided including the number of GitHub stars.
</ResponseField>
<ResponseField name="url" type="string">
If `link`: What the button links to.
If `github`: Link to the repository to load GitHub information from.
</ResponseField>
<ResponseField name="name" type="string">
Text inside the button. Only required if `type` is a `link`.
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="versions" type="string[]">
Array of version names. Only use this if you want to show different versions
of docs with a dropdown in the navigation bar.
</ResponseField>
<ResponseField name="anchors" type="Anchor[]">
An array of the anchors, includes the `icon`, `color`, and `url`.
<Expandable title="Anchor">
<ResponseField name="icon" type="string">
The [Font Awesome](https://fontawesome.com/search?q=heart) icon used to feature the anchor.
Example: `comments`
</ResponseField>
<ResponseField name="name" type="string">
The name of the anchor label.
Example: `Community`
</ResponseField>
<ResponseField name="url" type="string">
The start of the URL that marks what pages go in the anchor. Generally, this is the name of the folder you put your pages in.
</ResponseField>
<ResponseField name="color" type="string">
The hex color of the anchor icon background. Can also be a gradient if you pass an object with the properties `from` and `to` that are each a hex color.
</ResponseField>
<ResponseField name="version" type="string">
Used if you want to hide an anchor until the correct docs version is selected.
</ResponseField>
<ResponseField name="isDefaultHidden" type="boolean" default="false">
Pass `true` if you want to hide the anchor until you directly link someone to docs inside it.
</ResponseField>
<ResponseField name="iconType" default="duotone" type="string">
One of: "brands", "duotone", "light", "sharp-solid", "solid", or "thin"
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="topAnchor" type="Object">
Override the default configurations for the top-most anchor.
<Expandable title="Object">
<ResponseField name="name" default="Documentation" type="string">
The name of the top-most anchor
</ResponseField>
<ResponseField name="icon" default="book-open" type="string">
Font Awesome icon.
</ResponseField>
<ResponseField name="iconType" default="duotone" type="string">
One of: "brands", "duotone", "light", "sharp-solid", "solid", or "thin"
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="tabs" type="Tabs[]">
An array of navigational tabs.
<Expandable title="Tabs">
<ResponseField name="name" type="string">
The name of the tab label.
</ResponseField>
<ResponseField name="url" type="string">
The start of the URL that marks what pages go in the tab. Generally, this
is the name of the folder you put your pages in.
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="api" type="API">
Configuration for API settings. Learn more about API pages at [API Components](/api-playground/demo).
<Expandable title="API">
<ResponseField name="baseUrl" type="string">
The base url for all API endpoints. If `baseUrl` is an array, it will enable for multiple base url
options that the user can toggle.
</ResponseField>
<ResponseField name="auth" type="Auth">
<Expandable title="Auth">
<ResponseField name="method" type='"bearer" | "basic" | "key"'>
The authentication strategy used for all API endpoints.
</ResponseField>
<ResponseField name="name" type="string">
The name of the authentication parameter used in the API playground.
If method is `basic`, the format should be `[usernameName]:[passwordName]`
</ResponseField>
<ResponseField name="inputPrefix" type="string">
The default value that's designed to be a prefix for the authentication input field.
E.g. If an `inputPrefix` of `AuthKey` would inherit the default input result of the authentication field as `AuthKey`.
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="playground" type="Playground">
Configurations for the API playground
<Expandable title="Playground">
<ResponseField name="mode" default="show" type='"show" | "simple" | "hide"'>
Whether the playground is showing, hidden, or only displaying the endpoint with no added user interactivity `simple`
Learn more at the [playground guides](/api-playground/demo)
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="maintainOrder" type="boolean">
Enabling this flag ensures that key ordering in OpenAPI pages matches the key ordering defined in the OpenAPI file.
<Warning>This behavior will soon be enabled by default, at which point this field will be deprecated.</Warning>
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="openapi" type="string | string[]">
A string or an array of strings of URL(s) or relative path(s) pointing to your
OpenAPI file.
Examples:
<CodeGroup>
```json Absolute
"openapi": "https://example.com/openapi.json"
```
```json Relative
"openapi": "/openapi.json"
```
```json Multiple
"openapi": ["https://example.com/openapi1.json", "/openapi2.json", "/openapi3.json"]
```
</CodeGroup>
</ResponseField>
<ResponseField name="footerSocials" type="FooterSocials">
An object of social media accounts where the key:property pair represents the social media platform and the account url.
Example:
```json
{
"x": "https://x.com/mintlify",
"website": "https://mintlify.com"
}
```
<Expandable title="FooterSocials">
<ResponseField name="[key]" type="string">
One of the following values `website`, `facebook`, `x`, `discord`, `slack`, `github`, `linkedin`, `instagram`, `hacker-news`
Example: `x`
</ResponseField>
<ResponseField name="property" type="string">
The URL to the social platform.
Example: `https://x.com/mintlify`
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="feedback" type="Feedback">
Configurations to enable feedback buttons
<Expandable title="Feedback">
<ResponseField name="suggestEdit" type="boolean" default="false">
Enables a button to allow users to suggest edits via pull requests
</ResponseField>
<ResponseField name="raiseIssue" type="boolean" default="false">
Enables a button to allow users to raise an issue about the documentation
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="modeToggle" type="ModeToggle">
Customize the dark mode toggle.
<Expandable title="ModeToggle">
<ResponseField name="default" type={'"light" or "dark"'}>
Set if you always want to show light or dark mode for new users. When not
set, we default to the same mode as the user's operating system.
</ResponseField>
<ResponseField name="isHidden" type="boolean" default="false">
Set to true to hide the dark/light mode toggle. You can combine `isHidden` with `default` to force your docs to only use light or dark mode. For example:
<CodeGroup>
```json Only Dark Mode
"modeToggle": {
"default": "dark",
"isHidden": true
}
```
```json Only Light Mode
"modeToggle": {
"default": "light",
"isHidden": true
}
```
</CodeGroup>
</ResponseField>
</Expandable>
</ResponseField>
<ResponseField name="backgroundImage" type="string">
A background image to be displayed behind every page. See example with
[Infisical](https://infisical.com/docs) and [FRPC](https://frpc.io).
</ResponseField>

BIN
docs/favicon.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

19
docs/favicon.svg Normal file
View File

@@ -0,0 +1,19 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.06145 23.1079C5.26816 22.3769 -3.39077 20.6274 1.4173 5.06384C9.6344 6.09939 16.9728 14.0644 9.06145 23.1079Z" fill="url(#paint0_linear_17557_2021)"/>
<path d="M8.91928 23.0939C5.27642 21.2223 0.78371 4.20891 17.0071 0C20.7569 7.19341 19.6212 16.5452 8.91928 23.0939Z" fill="url(#paint1_linear_17557_2021)"/>
<path d="M8.91388 23.0788C8.73534 19.8817 10.1585 9.08525 23.5699 13.1107C23.1812 20.1229 18.984 26.4182 8.91388 23.0788Z" fill="url(#paint2_linear_17557_2021)"/>
<defs>
<linearGradient id="paint0_linear_17557_2021" x1="3.77557" y1="5.91571" x2="5.23185" y2="21.5589" gradientUnits="userSpaceOnUse">
<stop stop-color="#18E299"/>
<stop offset="1" stop-color="#15803D"/>
</linearGradient>
<linearGradient id="paint1_linear_17557_2021" x1="12.1711" y1="-0.718425" x2="10.1897" y2="22.9832" gradientUnits="userSpaceOnUse">
<stop stop-color="#16A34A"/>
<stop offset="1" stop-color="#4ADE80"/>
</linearGradient>
<linearGradient id="paint2_linear_17557_2021" x1="23.1327" y1="15.353" x2="9.33841" y2="18.5196" gradientUnits="userSpaceOnUse">
<stop stop-color="#4ADE80"/>
<stop offset="1" stop-color="#0D9373"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,338 @@
---
title: 'Authentication & Security'
description: 'Configure authentication and security settings for MCPHub'
---
## Overview
MCPHub provides flexible authentication mechanisms to secure your MCP server management platform. The system supports multiple authentication methods and role-based access control.
## Authentication Methods
### Environment-based Authentication
Configure basic authentication using environment variables:
```bash
# Basic auth credentials
AUTH_USERNAME=admin
AUTH_PASSWORD=your-secure-password
# JWT settings
JWT_SECRET=your-jwt-secret-key
JWT_EXPIRES_IN=24h
```
### Database Authentication
For production deployments, enable database-backed user management:
```json
{
"auth": {
"provider": "database",
"database": {
"url": "postgresql://user:pass@localhost:5432/mcphub",
"userTable": "users"
}
}
}
```
## User Management
### Creating Users
Create users via the admin interface or API:
```bash
# Via API
curl -X POST http://localhost:3000/api/auth/users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-d '{
"username": "newuser",
"email": "user@example.com",
"password": "securepassword",
"role": "user"
}'
```
### User Roles
MCPHub supports role-based access control:
- **Admin**: Full system access, user management, server configuration
- **Manager**: Server management, group management, monitoring
- **User**: Basic server access within assigned groups
- **Viewer**: Read-only access to assigned resources
## Group-based Access Control
### Assigning Users to Groups
```bash
# Add user to group
curl -X POST http://localhost:3000/api/groups/{groupId}/users \
-H "Authorization: Bearer $TOKEN" \
-d '{"userId": "user123"}'
```
### Group Permissions
Configure group-level permissions:
```json
{
"groupId": "dev-team",
"permissions": {
"servers": ["read", "write", "execute"],
"tools": ["read", "execute"],
"logs": ["read"],
"config": ["read"]
}
}
```
## API Authentication
### JWT Token Authentication
```javascript
// Login to get token
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: 'your-username',
password: 'your-password',
}),
});
const { token } = await response.json();
// Use token for authenticated requests
const serversResponse = await fetch('/api/servers', {
headers: { Authorization: `Bearer ${token}` },
});
```
### API Key Authentication
For service-to-service communication:
```bash
# Generate API key
curl -X POST http://localhost:3000/api/auth/api-keys \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-d '{
"name": "my-service",
"permissions": ["servers:read", "tools:execute"]
}'
# Use API key
curl -H "X-API-Key: your-api-key" \
http://localhost:3000/api/servers
```
## Security Configuration
### HTTPS Setup
Configure HTTPS for production:
```yaml
# docker-compose.yml
services:
mcphub:
environment:
- HTTPS_ENABLED=true
- SSL_CERT_PATH=/certs/cert.pem
- SSL_KEY_PATH=/certs/key.pem
volumes:
- ./certs:/certs:ro
```
### CORS Configuration
Configure CORS for web applications:
```json
{
"cors": {
"origin": ["https://your-frontend.com"],
"credentials": true,
"methods": ["GET", "POST", "PUT", "DELETE"]
}
}
```
### Rate Limiting
Protect against abuse with rate limiting:
```json
{
"rateLimit": {
"windowMs": 900000,
"max": 100,
"message": "Too many requests from this IP"
}
}
```
## Session Management
### Session Configuration
```json
{
"session": {
"secret": "your-session-secret",
"cookie": {
"secure": true,
"httpOnly": true,
"maxAge": 86400000
},
"store": "redis",
"redis": {
"host": "localhost",
"port": 6379
}
}
}
```
### Logout and Session Cleanup
```javascript
// Logout endpoint
app.post('/api/auth/logout', (req, res) => {
req.session.destroy();
res.json({ message: 'Logged out successfully' });
});
```
## Security Best Practices
### Password Security
- Use strong password requirements
- Implement password hashing with bcrypt
- Support password reset functionality
- Enable two-factor authentication (2FA)
### Token Security
- Use secure JWT secrets
- Implement token rotation
- Set appropriate expiration times
- Store tokens securely in httpOnly cookies
### Network Security
- Use HTTPS in production
- Implement proper CORS policies
- Enable request validation
- Use security headers (helmet.js)
### Monitoring Security Events
```javascript
// Log security events
const auditLog = {
event: 'login_attempt',
user: username,
ip: req.ip,
userAgent: req.headers['user-agent'],
success: true,
timestamp: new Date(),
};
```
## Troubleshooting
### Common Authentication Issues
**Invalid Credentials**
```bash
# Check user exists and password is correct
curl -X POST http://localhost:3000/api/auth/verify \
-d '{"username": "user", "password": "pass"}'
```
**Token Expiration**
```javascript
// Handle token refresh
if (response.status === 401) {
const newToken = await refreshToken();
// Retry request with new token
}
```
**Permission Denied**
```bash
# Check user permissions
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:3000/api/auth/permissions
```
### Debug Authentication
Enable authentication debugging:
```bash
DEBUG=mcphub:auth npm start
```
## Integration Examples
### Frontend Integration
```javascript
// React authentication hook
const useAuth = () => {
const [user, setUser] = useState(null);
const login = async (credentials) => {
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(credentials),
});
if (response.ok) {
const userData = await response.json();
setUser(userData.user);
return true;
}
return false;
};
return { user, login };
};
```
### Middleware Integration
```javascript
// Express middleware
const authMiddleware = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
} catch (error) {
res.status(401).json({ error: 'Invalid token' });
}
};
```

View File

@@ -0,0 +1,578 @@
---
title: 'Group Management'
description: 'Organize servers into logical groups for streamlined access control'
---
## Overview
Group Management in MCPHub allows you to organize your MCP servers into logical collections based on functionality, use case, or access requirements. This enables fine-grained control over which tools are available to different AI clients and users.
## Core Concepts
### What are Groups?
Groups are named collections of MCP servers that can be accessed through dedicated endpoints. Instead of connecting to all servers at once, AI clients can connect to specific groups to access only relevant tools.
### Benefits of Groups
- **Focused Tool Access**: AI clients see only relevant tools for their use case
- **Better Performance**: Reduced tool discovery overhead
- **Enhanced Security**: Limit access to sensitive tools
- **Improved Organization**: Logical separation of functionality
- **Simplified Management**: Easier to manage related servers together
## Creating Groups
### Via Dashboard
1. **Navigate to Groups Section**: Click "Groups" in the main navigation
2. **Click "Create Group"**: Start the group creation process
3. **Fill Group Details**:
- **Name**: Unique identifier for the group
4. **Add Servers**: Select servers to include in the group
### Via API
Create groups programmatically:
```bash
curl -X POST http://localhost:3000/api/groups \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"name": "web-automation",
"servers": ["playwright", "fetch"]
}'
```
{/* ### Via Configuration File
Define groups in your `mcp_settings.json`:
```json
{
"mcpServers": {
"fetch": { "command": "uvx", "args": ["mcp-server-fetch"] },
"playwright": { "command": "npx", "args": ["@playwright/mcp@latest"] },
"slack": { "command": "npx", "args": ["@modelcontextprotocol/server-slack"] }
},
"groups": {
"web-tools": {
"name": "web",
"servers": ["fetch", "playwright"],
},
"communication": {
"name": "communication",
"servers": ["slack"],
}
}
}
``` */}
## Group Types and Use Cases
<AccordionGroup>
<Accordion title="Web Automation Group">
**Purpose**: Browser automation and web scraping
**Servers**:
- `playwright`: Browser automation
- `fetch`: HTTP requests and web scraping
- `selenium`: Alternative browser automation
**Use Cases**:
- Automated testing
- Data collection
- Web monitoring
- Content analysis
**Endpoint**: `http://localhost:3000/mcp/web-automation`
</Accordion>
<Accordion title="Data Processing Group">
**Purpose**: Data manipulation and analysis
**Servers**:
- `sqlite`: Database operations
- `filesystem`: File operations
- `spreadsheet`: Excel/CSV processing
**Use Cases**:
- Data analysis
- Report generation
- File processing
- Database queries
**Endpoint**: `http://localhost:3000/mcp/data-processing`
</Accordion>
<Accordion title="Communication Group">
**Purpose**: Messaging and collaboration
**Servers**:
- `slack`: Slack integration
- `discord`: Discord bot
- `email`: Email sending
- `sms`: SMS notifications
**Use Cases**:
- Team notifications
- Customer communication
- Alert systems
- Social media management
**Endpoint**: `http://localhost:3000/mcp/communication`
</Accordion>
<Accordion title="Development Group">
**Purpose**: Software development tools
**Servers**:
- `github`: GitHub operations
- `gitlab`: GitLab integration
- `docker`: Container management
- `kubernetes`: K8s operations
**Use Cases**:
- Code deployment
- Repository management
- CI/CD operations
- Infrastructure management
**Endpoint**: `http://localhost:3000/mcp/development`
</Accordion>
<Accordion title="AI/ML Group">
**Purpose**: Machine learning and AI tools
**Servers**:
- `openai`: OpenAI API integration
- `huggingface`: Hugging Face models
- `vector-db`: Vector database operations
**Use Cases**:
- Model inference
- Data embeddings
- Natural language processing
- Computer vision
**Endpoint**: `http://localhost:3000/mcp/ai-ml`
</Accordion>
</AccordionGroup>
{/* ## Group Access Control
### Access Levels
<Tabs>
<Tab title="Public">
**Public Groups**:
- Accessible to all authenticated users
- No additional permissions required
- Visible in group listings
- Default access level
```json
{
"name": "public-tools",
"accessLevel": "public",
"servers": ["fetch", "calculator"]
}
```
</Tab>
<Tab title="Private">
**Private Groups**:
- Only visible to group members
- Requires explicit user assignment
- Hidden from public listings
- Admin-controlled membership
```json
{
"name": "internal-tools",
"accessLevel": "private",
"members": ["user1", "user2"],
"servers": ["internal-api", "database"]
}
```
</Tab>
<Tab title="Restricted">
**Restricted Groups**:
- Role-based access control
- Requires specific permissions
- Audit logging enabled
- Time-limited access
```json
{
"name": "admin-tools",
"accessLevel": "restricted",
"requiredRoles": ["admin", "operator"],
"servers": ["system-control", "user-management"]
}
```
</Tab>
</Tabs>
### User Management
Assign users to groups:
```bash
# Add user to group
curl -X POST http://localhost:3000/api/groups/web-tools/members \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{"userId": "user123"}'
# Remove user from group
curl -X DELETE http://localhost:3000/api/groups/web-tools/members/user123 \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
# List group members
curl http://localhost:3000/api/groups/web-tools/members \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
``` */}
## Group Endpoints
### Accessing Groups
Each group gets its own MCP endpoint:
<Tabs>
<Tab title="HTTP MCP">
```
http://localhost:3000/mcp/{group-name}
```
Examples:
- `http://localhost:3000/mcp/web-tools`
- `http://localhost:3000/mcp/data-processing`
- `http://localhost:3000/mcp/communication`
</Tab>
<Tab title="SSE (Legacy)">
```
http://localhost:3000/sse/{group-name}
```
Examples:
- `http://localhost:3000/sse/web-tools`
- `http://localhost:3000/sse/data-processing`
- `http://localhost:3000/sse/communication`
</Tab>
</Tabs>
### Group Tool Discovery
When connecting to a group endpoint, AI clients will only see tools from servers within that group:
```bash
# List tools in web-tools group
curl -X POST http://localhost:3000/mcp/web-tools \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}'
```
Response will only include tools from `fetch` and `playwright` servers.
## Dynamic Group Management
### Adding Servers to Groups
<Tabs>
<Tab title="Dashboard">
1. Navigate to the group in the dashboard
2. Click "Manage Servers"
3. Select additional servers to add
4. Click "Save Changes"
</Tab>
<Tab title="API">
```bash
curl -X POST http://localhost:3000/api/groups/web-tools/servers \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{"serverId": "new-server"}'
```
</Tab>
</Tabs>
### Removing Servers from Groups
<Tabs>
<Tab title="Dashboard">
1. Navigate to the group in the dashboard
2. Click "Manage Servers"
3. Unselect servers to remove
4. Click "Save Changes"
</Tab>
<Tab title="API">
```bash
curl -X DELETE http://localhost:3000/api/groups/web-tools/servers/server-name \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
</Tab>
</Tabs>
{/* ### Batch Server Updates
Update multiple servers at once:
```bash
curl -X PUT http://localhost:3000/api/groups/web-tools/servers \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"servers": ["fetch", "playwright", "selenium"]
}'
``` */}
{/* ## Group Monitoring
### Group Status
Monitor group health and activity:
```bash
# Get group status
curl http://localhost:3000/api/groups/web-tools/status \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
Response includes:
- Number of active servers
- Tool count
- Active connections
- Recent activity
### Group Analytics
Track group usage:
```bash
# Get group analytics
curl http://localhost:3000/api/groups/web-tools/analytics \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
Metrics include:
- Request count by tool
- Response times
- Error rates
- User activity */}
{/* ## Advanced Group Features
### Nested Groups
Create hierarchical group structures:
```json
{
"groups": {
"development": {
"displayName": "Development Tools",
"subGroups": ["frontend-dev", "backend-dev", "devops"]
},
"frontend-dev": {
"displayName": "Frontend Development",
"servers": ["playwright", "webpack-server"],
"parent": "development"
},
"backend-dev": {
"displayName": "Backend Development",
"servers": ["database", "api-server"],
"parent": "development"
}
}
}
```
### Group Templates
Use templates for quick group creation:
```json
{
"groupTemplates": {
"web-project": {
"description": "Standard web project toolset",
"servers": ["fetch", "playwright", "filesystem"],
"accessLevel": "public"
},
"data-science": {
"description": "Data science and ML tools",
"servers": ["python-tools", "jupyter", "vector-db"],
"accessLevel": "private"
}
}
}
```
Apply template:
```bash
curl -X POST http://localhost:3000/api/groups/from-template \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"name": "my-web-project",
"template": "web-project",
"displayName": "My Web Project Tools"
}'
```
### Group Policies
Define policies for group behavior:
```json
{
"groupPolicies": {
"web-tools": {
"maxConcurrentConnections": 10,
"requestTimeout": 30000,
"rateLimiting": {
"requestsPerMinute": 100,
"burstLimit": 20
},
"allowedOrigins": ["localhost", "myapp.com"]
}
}
}
``` */}
## Best Practices
### Group Organization
<Tip>
**Organize by Use Case**: Group servers based on what users want to accomplish, not just technical
similarity.
</Tip>
<Tip>
**Keep Groups Focused**: Avoid creating groups with too many diverse tools. Smaller, focused
groups are more useful.
</Tip>
<Tip>
**Use Descriptive Names**: Choose names that clearly indicate the group's purpose and contents.
</Tip>
{/* ### Security Considerations
<Warning>
**Principle of Least Privilege**: Only give users access to groups they actually need.
</Warning>
<Warning>
**Sensitive Tool Isolation**: Keep sensitive tools in restricted groups with proper access
controls.
</Warning>
<Warning>
**Regular Access Reviews**: Periodically review group memberships and remove unnecessary access.
</Warning> */}
### Performance Optimization
<Info>
**Balance Group Size**: Very large groups may have slower tool discovery. Consider splitting into
smaller groups.
</Info>
<Info>
**Monitor Usage**: Use analytics to identify which groups are heavily used and optimize
accordingly.
</Info>
## Troubleshooting
<AccordionGroup>
<Accordion title="Group Not Accessible">
**Check:**
- User has proper permissions
- Group exists and is active
- Servers in group are running
- Network connectivity
**Solutions:**
1. Verify user group membership
2. Check group configuration
3. Test individual server connections
4. Review access logs
</Accordion>
<Accordion title="Tools Missing from Group">
**Possible causes:**
- Server not properly added to group
- Server is not running
- Tool discovery failed
- Caching issues
**Debug steps:**
1. Verify server is in group configuration
2. Check server status
3. Force refresh tool discovery
4. Clear group cache
</Accordion>
<Accordion title="Group Performance Issues">
**Common issues:**
- Too many servers in group
- Slow server responses
- Network latency
- Resource constraints
**Optimizations:**
1. Split large groups
2. Monitor server performance
3. Implement request caching
4. Use connection pooling
</Accordion>
</AccordionGroup>
## Next Steps
<CardGroup cols={2}>
<Card title="Smart Routing" icon="route" href="/features/smart-routing">
AI-powered tool discovery across groups
</Card>
<Card title="Authentication" icon="shield" href="/features/authentication">
User management and access control
</Card>
<Card title="API Reference" icon="code" href="/api-reference/groups">
Complete group management API
</Card>
<Card title="Configuration" icon="cog" href="/configuration/mcp-settings">
Advanced group configuration options
</Card>
</CardGroup>

View File

@@ -0,0 +1,526 @@
---
title: 'Monitoring & Logging'
description: 'Monitor your MCP servers and analyze system logs with MCPHub'
---
## Overview
MCPHub provides comprehensive monitoring and logging capabilities to help you track server performance, debug issues, and maintain system health.
## Real-time Monitoring
### Server Status Dashboard
The MCPHub dashboard provides real-time monitoring of all registered MCP servers:
- **Server Health**: Online/offline status with automatic health checks
- **Response Times**: Average, min, max response times per server
- **Request Volume**: Requests per second/minute/hour
- **Error Rates**: Success/failure ratios and error trends
- **Resource Usage**: Memory and CPU utilization (when available)
### Health Check Configuration
Configure health checks for your MCP servers:
```json
{
"healthCheck": {
"enabled": true,
"interval": 30000,
"timeout": 5000,
"retries": 3,
"endpoints": {
"ping": "/health",
"tools": "/tools/list"
}
}
}
```
### Monitoring API
Get monitoring data programmatically:
```bash
# Get server health status
curl http://localhost:3000/api/monitoring/health
# Get performance metrics
curl http://localhost:3000/api/monitoring/metrics?server=my-server&range=1h
# Get system overview
curl http://localhost:3000/api/monitoring/overview
```
## Logging System
### Log Levels
MCPHub supports standard log levels:
- **ERROR**: Critical errors requiring immediate attention
- **WARN**: Warning conditions that should be monitored
- **INFO**: General operational messages
- **DEBUG**: Detailed debugging information
- **TRACE**: Very detailed trace information
### Log Configuration
Configure logging in your environment:
```bash
# Set log level
LOG_LEVEL=info
# Enable structured logging
LOG_FORMAT=json
# Log file location
LOG_FILE=/var/log/mcphub/app.log
# Enable request logging
ENABLE_REQUEST_LOGS=true
```
### Structured Logging
MCPHub uses structured logging for better analysis:
```json
{
"timestamp": "2024-01-20T10:30:00Z",
"level": "info",
"message": "MCP server request completed",
"server": "github-mcp",
"tool": "search_repositories",
"duration": 245,
"status": "success",
"requestId": "req_123456",
"userId": "user_789"
}
```
## Log Management
### Log Storage Options
#### File-based Logging
```yaml
# docker-compose.yml
services:
mcphub:
volumes:
- ./logs:/app/logs
environment:
- LOG_FILE=/app/logs/mcphub.log
- LOG_ROTATION=daily
- LOG_MAX_SIZE=100MB
- LOG_MAX_FILES=7
```
#### Database Logging
```json
{
"logging": {
"database": {
"enabled": true,
"table": "logs",
"retention": "30d",
"indexes": ["timestamp", "level", "server"]
}
}
}
```
#### External Log Services
```bash
# Syslog integration
SYSLOG_ENABLED=true
SYSLOG_HOST=localhost
SYSLOG_PORT=514
SYSLOG_FACILITY=local0
# ELK Stack integration
ELASTICSEARCH_URL=http://localhost:9200
ELASTICSEARCH_INDEX=mcphub-logs
```
### Log Rotation
Automatic log rotation configuration:
```json
{
"logRotation": {
"enabled": true,
"maxSize": "100MB",
"maxFiles": 10,
"compress": true,
"interval": "daily"
}
}
```
## Metrics Collection
### System Metrics
MCPHub collects various system metrics:
```javascript
// Example metrics collected
{
"timestamp": "2024-01-20T10:30:00Z",
"metrics": {
"requests": {
"total": 1547,
"success": 1523,
"errors": 24,
"rate": 12.5
},
"servers": {
"online": 8,
"offline": 2,
"total": 10
},
"performance": {
"avgResponseTime": 156,
"p95ResponseTime": 324,
"p99ResponseTime": 567
},
"system": {
"memoryUsage": "245MB",
"cpuUsage": "15%",
"uptime": "72h 35m"
}
}
}
```
### Custom Metrics
Add custom metrics for your use case:
```javascript
// Custom metric example
const customMetric = {
name: 'tool_usage',
type: 'counter',
tags: {
server: 'github-mcp',
tool: 'search_repositories',
result: 'success',
},
value: 1,
};
// Send to metrics endpoint
await fetch('/api/monitoring/metrics', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(customMetric),
});
```
## Alerting
### Alert Configuration
Set up alerts for critical conditions:
```json
{
"alerts": {
"serverDown": {
"condition": "server.status == 'offline'",
"duration": "5m",
"severity": "critical",
"channels": ["email", "slack"]
},
"highErrorRate": {
"condition": "errors.rate > 0.1",
"duration": "2m",
"severity": "warning",
"channels": ["slack"]
},
"slowResponse": {
"condition": "response.p95 > 1000",
"duration": "5m",
"severity": "warning",
"channels": ["email"]
}
}
}
```
### Notification Channels
#### Email Notifications
```bash
# Email configuration
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=alerts@yourcompany.com
SMTP_PASS=your-app-password
ALERT_EMAIL_TO=admin@yourcompany.com
```
#### Slack Integration
```bash
# Slack webhook
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
SLACK_CHANNEL=#mcphub-alerts
```
#### Webhook Notifications
```json
{
"webhooks": [
{
"url": "https://your-service.com/webhooks/mcphub",
"events": ["server.down", "error.rate.high"],
"headers": {
"Authorization": "Bearer your-token"
}
}
]
}
```
## Log Analysis
### Query Logs
Use the logs API to query and analyze logs:
```bash
# Get recent errors
curl "http://localhost:3000/api/logs?level=error&since=1h"
# Search logs by server
curl "http://localhost:3000/api/logs?server=github-mcp&limit=100"
# Get logs for specific request
curl "http://localhost:3000/api/logs?requestId=req_123456"
# Filter by time range
curl "http://localhost:3000/api/logs?from=2024-01-20T00:00:00Z&to=2024-01-20T23:59:59Z"
```
### Log Aggregation
Aggregate logs for insights:
```bash
# Error summary by server
curl "http://localhost:3000/api/logs/aggregate?groupBy=server&level=error&since=24h"
# Request volume over time
curl "http://localhost:3000/api/logs/aggregate?groupBy=hour&type=request&since=7d"
```
## Performance Monitoring
### Response Time Tracking
Monitor MCP server response times:
```javascript
// Response time metrics
{
"server": "github-mcp",
"tool": "search_repositories",
"metrics": {
"calls": 156,
"avgTime": 234,
"minTime": 89,
"maxTime": 1205,
"p50": 201,
"p95": 567,
"p99": 892
}
}
```
### Error Rate Monitoring
Track error rates and patterns:
```bash
# Get error rates by server
curl "http://localhost:3000/api/monitoring/errors?groupBy=server&since=1h"
# Get error details
curl "http://localhost:3000/api/monitoring/errors?server=github-mcp&details=true"
```
## Integration with External Tools
### Prometheus Integration
Export metrics to Prometheus:
```yaml
# prometheus.yml
scrape_configs:
- job_name: 'mcphub'
static_configs:
- targets: ['localhost:3000']
metrics_path: '/api/monitoring/prometheus'
scrape_interval: 30s
```
### Grafana Dashboards
Import MCPHub Grafana dashboard:
```json
{
"dashboard": {
"title": "MCPHub Monitoring",
"panels": [
{
"title": "Server Status",
"type": "stat",
"targets": [
{
"expr": "mcphub_servers_online",
"legendFormat": "Online"
}
]
},
{
"title": "Request Rate",
"type": "graph",
"targets": [
{
"expr": "rate(mcphub_requests_total[5m])",
"legendFormat": "Requests/sec"
}
]
}
]
}
}
```
### ELK Stack Integration
Configure Logstash for log processing:
```ruby
# logstash.conf
input {
beats {
port => 5044
}
}
filter {
if [fields][service] == "mcphub" {
json {
source => "message"
}
date {
match => [ "timestamp", "ISO8601" ]
}
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "mcphub-logs-%{+YYYY.MM.dd}"
}
}
```
## Troubleshooting
### Common Monitoring Issues
**Missing Metrics**
```bash
# Check metrics endpoint
curl http://localhost:3000/api/monitoring/health
# Verify configuration
grep -r "monitoring" /path/to/config/
```
**Log File Issues**
```bash
# Check log file permissions
ls -la /var/log/mcphub/
# Verify disk space
df -h /var/log/
# Check log rotation
logrotate -d /etc/logrotate.d/mcphub
```
**Performance Issues**
```bash
# Monitor system resources
top -p $(pgrep -f mcphub)
# Check database connections
curl http://localhost:3000/api/monitoring/database
# Analyze slow queries
curl http://localhost:3000/api/monitoring/slow-queries
```
### Debug Mode
Enable debug logging for troubleshooting:
```bash
# Enable debug mode
DEBUG=mcphub:* npm start
# Or set environment variable
export DEBUG=mcphub:monitoring,mcphub:logging
```
## Best Practices
### Log Management
- Use structured logging with consistent formats
- Implement proper log levels and filtering
- Set up log rotation and retention policies
- Monitor log file sizes and disk usage
### Monitoring Setup
- Configure appropriate health check intervals
- Set up alerts for critical conditions
- Monitor both system and application metrics
- Use dashboards for visual monitoring
### Performance Optimization
- Index log database tables appropriately
- Use log sampling for high-volume scenarios
- Implement proper caching for metrics
- Regular cleanup of old logs and metrics
### Security Considerations
- Sanitize sensitive data in logs
- Secure access to monitoring endpoints
- Use authentication for external integrations
- Encrypt log transmission when using external services

141
docs/features/oauth.mdx Normal file
View File

@@ -0,0 +1,141 @@
# OAuth Support
## At a Glance
- Covers end-to-end OAuth 2.0 Authorization Code with PKCE for upstream MCP servers.
- Supports automatic discovery from `WWW-Authenticate` responses and RFC 8414 metadata.
- Implements dynamic client registration (RFC 7591) and resource indicators (RFC 8707).
- Persists client credentials and tokens to `mcp_settings.json` for reconnects.
## When MCPHub Switches to OAuth
1. MCPHub calls an MCP server that requires authorization and receives `401 Unauthorized`.
2. The response exposes a `WWW-Authenticate` header pointing to protected resource metadata (`authorization_server` or `as_uri`).
3. MCPHub discovers the authorization server metadata, registers (if needed), and opens the browser so the user can authorize once.
4. After the callback is handled, MCPHub reconnects with fresh tokens and resumes requests transparently.
> MCPHub logs each stage (discovery, registration, authorization URL, token exchange) in the server detail view and the backend logs.
## Quick Start by Server Type
### Servers with Dynamic Registration Support
Some servers expose complete OAuth metadata and allow dynamic client registration. For example, Vercel and Linear MCP servers only need their SSE endpoint configured:
```json
{
"mcpServers": {
"vercel": {
"type": "sse",
"url": "https://mcp.vercel.com"
},
"linear": {
"type": "sse",
"url": "https://mcp.linear.app/mcp"
}
}
}
```
- MCPHub discovers the authorization server, registers the client, and handles PKCE automatically.
- Tokens are stored in `mcp_settings.json`; no additional dashboard configuration is needed.
### Servers Requiring Manual Client Provisioning
Other providers do not support dynamic registration. GitHubs MCP endpoint (`https://api.githubcopilot.com/mcp/`) is one example. To connect:
1. Create an OAuth App in the providers console (for GitHub, go to **Settings → Developer settings → OAuth Apps**).
2. Set the callback/redirect URL to `http://localhost:3000/oauth/callback` (or your deployed dashboard domain).
3. Copy the issued client ID and client secret.
4. Supply the credentials through the MCPHub dashboard or by editing `mcp_settings.json` as shown below.
```json
{
"mcpServers": {
"github": {
"type": "sse",
"url": "https://api.githubcopilot.com/mcp/",
"oauth": {
"clientId": "${GITHUB_OAUTH_APP_ID}",
"clientSecret": "${GITHUB_OAUTH_APP_SECRET}",
"scopes": ["replace-with-provider-scope"],
"resource": "https://api.githubcopilot.com"
}
}
}
}
```
- MCPHub skips dynamic registration and uses the credentials you provide to complete the OAuth exchange.
- Update the dashboard or configuration file whenever you rotate secrets.
- Replace `scopes` with the exact scope strings required by the provider.
## Configuration Options
You can rely on auto-detection for most servers or declare OAuth settings explicitly in `mcp_settings.json`. Only populate the fields you need.
### Basic Auto Detection (Minimal Config)
```json
{
"mcpServers": {
"secured-sse": {
"type": "sse",
"url": "https://mcp.example.com/sse",
"oauth": {
"scopes": ["mcp.tools", "mcp.prompts"],
"resource": "https://mcp.example.com"
}
}
}
}
```
- MCPHub will discover the authorization server from challenge headers and walk the user through authorization automatically.
- Tokens (including refresh tokens) are stored on disk and reused on restart.
### Static Client Credentials (Bring Your Own Client)
```json
{
"oauth": {
"clientId": "mcphub-client",
"clientSecret": "replace-me-if-required",
"authorizationEndpoint": "https://auth.example.com/oauth/authorize",
"tokenEndpoint": "https://auth.example.com/oauth/token",
"redirectUri": "http://localhost:3000/oauth/callback"
}
}
```
- Use this when the authorization server requires manual client provisioning.
- `redirectUri` defaults to `http://localhost:3000/oauth/callback`; override it when running behind a custom domain.
### Dynamic Client Registration (RFC 7591)
```json
{
"oauth": {
"dynamicRegistration": {
"enabled": true,
"issuer": "https://auth.example.com",
"metadata": {
"client_name": "MCPHub",
"redirect_uris": [
"http://localhost:3000/oauth/callback",
"https://mcphub.example.com/oauth/callback"
],
"scope": "mcp.tools mcp.prompts",
"grant_types": ["authorization_code", "refresh_token"]
},
"initialAccessToken": "optional-token-if-required"
},
"scopes": ["mcp.tools", "mcp.prompts"],
"resource": "https://mcp.example.com"
}
}
```
- MCPHub discovers endpoints via `issuer`, registers itself, and persists the issued `client_id`/`client_secret`.
- Provide `initialAccessToken` only when the registration endpoint is protected.
## Authorization Flow
1. **Initialization** On startup MCPHub processes every server entry, discovers metadata, and registers the client if `dynamicRegistration.enabled` is true.
2. **User Authorization** Initiating a connection launches the system browser to the servers authorize page with PKCE parameters.
3. **Callback Handling** The built-in route (`/oauth/callback`) verifies the `state`, completes the token exchange, and saves the tokens via the MCP SDK.
4. **Token Lifecycle** Access and refresh tokens are cached in memory, refreshed automatically, and written back to `mcp_settings.json`.
## Tips & Troubleshooting
- Confirm that the redirect URI used during authorization exactly matches one of the `redirect_uris` registered with the authorization server.
- When running behind HTTPS, expose the callback URL publicly or configure a reverse proxy at `/oauth/callback`.
- If discovery fails, supply `authorizationEndpoint` and `tokenEndpoint` explicitly to bypass metadata lookup.
- Remove stale tokens from `mcp_settings.json` if an authorization server revokes access—MCPHub will prompt for a fresh login on the next request.

View File

@@ -0,0 +1,509 @@
---
title: 'Server Management'
description: 'Centrally manage multiple MCP servers with hot-swappable configuration'
---
## Overview
MCPHub's server management system allows you to centrally configure, monitor, and control multiple MCP (Model Context Protocol) servers from a single dashboard. All changes are applied in real-time without requiring server restarts.
## Adding MCP Servers
### Via Dashboard
1. **Access the Dashboard**: Navigate to `http://localhost:3000` and log in
2. **Click "Add Server"**: Located in the servers section
3. **Fill Server Details**:
- **Name**: Unique identifier for the server
- **Command**: Executable command (e.g., `npx`, `uvx`, `python`)
- **Arguments**: Array of command arguments
- **Environment Variables**: Key-value pairs for environment setup
- **Working Directory**: Optional working directory for the command
### Via Configuration File
Edit your `mcp_settings.json` file:
```json
{
"mcpServers": {
"server-name": {
"command": "command-to-run",
"args": ["arg1", "arg2"],
"env": {
"API_KEY": "your-api-key",
"CONFIG_VALUE": "some-value"
},
"cwd": "/optional/working/directory"
}
}
}
```
### Via API
Use the REST API to add servers programmatically:
```bash
curl -X POST http://localhost:3000/api/servers \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"name": "fetch-server",
"command": "uvx",
"args": ["mcp-server-fetch"],
"env": {}
}'
```
## Popular MCP Server Examples
<AccordionGroup>
<Accordion title="Web Fetch Server">
Provides web scraping and HTTP request capabilities:
```json
{
"fetch": {
"command": "uvx",
"args": ["mcp-server-fetch"]
}
}
```
**Available Tools:**
- `fetch`: Make HTTP requests
- `fetch_html`: Scrape web pages
- `fetch_json`: Get JSON data from APIs
</Accordion>
<Accordion title="Playwright Browser Automation">
Browser automation for web interactions:
```json
{
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest", "--headless"]
}
}
```
**Available Tools:**
- `playwright_navigate`: Navigate to web pages
- `playwright_screenshot`: Take screenshots
- `playwright_click`: Click elements
- `playwright_fill`: Fill forms
</Accordion>
<Accordion title="File System Operations">
File and directory management:
```json
{
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/allowed/path"]
}
}
```
**Available Tools:**
- `read_file`: Read file contents
- `write_file`: Write to files
- `create_directory`: Create directories
- `list_directory`: List directory contents
</Accordion>
<Accordion title="SQLite Database">
Database operations:
```json
{
"sqlite": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-sqlite", "/path/to/database.db"]
}
}
```
**Available Tools:**
- `execute_query`: Execute SQL queries
- `describe_tables`: Get table schemas
- `create_table`: Create new tables
</Accordion>
<Accordion title="Slack Integration">
Slack workspace integration:
```json
{
"slack": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-slack"],
"env": {
"SLACK_BOT_TOKEN": "xoxb-your-bot-token",
"SLACK_TEAM_ID": "T1234567890"
}
}
}
```
**Available Tools:**
- `send_slack_message`: Send messages to channels
- `list_slack_channels`: List available channels
- `get_slack_thread`: Get thread messages
</Accordion>
<Accordion title="GitHub Integration">
GitHub repository operations:
```json
{
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_your_token"
}
}
}
```
**Available Tools:**
- `create_or_update_file`: Create/update repository files
- `search_repositories`: Search GitHub repositories
- `create_issue`: Create issues
- `create_pull_request`: Create pull requests
</Accordion>
<Accordion title="Google Drive">
Google Drive file operations:
```json
{
"gdrive": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-gdrive"],
"env": {
"GDRIVE_CLIENT_ID": "your-client-id",
"GDRIVE_CLIENT_SECRET": "your-client-secret",
"GDRIVE_REDIRECT_URI": "your-redirect-uri"
}
}
}
```
**Available Tools:**
- `gdrive_search`: Search files and folders
- `gdrive_read`: Read file contents
- `gdrive_create`: Create new files
</Accordion>
<Accordion title="Amap Maps (China)">
Chinese mapping and location services:
```json
{
"amap": {
"command": "npx",
"args": ["-y", "@amap/amap-maps-mcp-server"],
"env": {
"AMAP_MAPS_API_KEY": "your-api-key"
}
}
}
```
**Available Tools:**
- `search_location`: Search for locations
- `get_directions`: Get route directions
- `reverse_geocode`: Convert coordinates to addresses
</Accordion>
</AccordionGroup>
## Server Lifecycle Management
### Starting Servers
Servers are automatically started when:
- MCPHub boots up
- A server is added via the dashboard or API
- A server configuration is updated
- A stopped server is manually restarted
### Stopping Servers
You can stop servers:
- **Via Dashboard**: Toggle the server status switch
- **Via API**: Send a POST request to `/api/servers/{name}/toggle`
- **Automatically**: Servers stop if they crash or encounter errors
### Restarting Servers
Servers are automatically restarted:
- When configuration changes are made
- After environment variable updates
- When manually triggered via dashboard or API
## Server Status Monitoring
### Status Indicators
Each server displays a status indicator:
- 🟢 **Running**: Server is active and responding
- 🟡 **Starting**: Server is initializing
- 🔴 **Stopped**: Server is not running
- ⚠️ **Error**: Server encountered an error
### Real-time Logs
View server logs in real-time:
1. **Dashboard Logs**: Click on a server to view its logs
2. **API Logs**: Access logs via `/api/logs` endpoint
3. **Streaming Logs**: Subscribe to log streams via WebSocket
### Health Checks
MCPHub automatically performs health checks:
- **Initialization Check**: Verifies server starts successfully
- **Tool Discovery**: Confirms available tools are detected
- **Response Check**: Tests server responsiveness
- **Resource Monitoring**: Tracks CPU and memory usage
## Configuration Management
### Environment Variables
Servers can use environment variables for configuration:
```json
{
"server-name": {
"command": "python",
"args": ["server.py"],
"env": {
"API_KEY": "${YOUR_API_KEY}",
"DEBUG": "true",
"MAX_CONNECTIONS": "10"
}
}
}
```
**Environment Variable Expansion:**
- `${VAR_NAME}`: Expands to environment variable value
- `${VAR_NAME:-default}`: Uses default if variable not set
- `${VAR_NAME:+value}`: Uses value if variable is set
{/* ### Working Directory
Set the working directory for server execution:
```json
{
"server-name": {
"command": "./local-script.sh",
"args": [],
"cwd": "/path/to/server/directory"
}
}
``` */}
### Command Variations
Different ways to specify server commands:
<Tabs>
<Tab title="npm/npx">
```json
{
"npm-server": {
"command": "npx",
"args": ["-y", "package-name", "--option", "value"]
}
}
```
</Tab>
<Tab title="Python/uvx">
```json
{
"python-server": {
"command": "uvx",
"args": ["package-name", "--config", "config.json"]
}
}
```
</Tab>
{/* <Tab title="Direct Python">
```json
{
"direct-python": {
"command": "python",
"args": ["-m", "module_name", "--arg", "value"]
}
}
```
</Tab>
<Tab title="Local Script">
```json
{
"local-script": {
"command": "./server.sh",
"args": ["--port", "8080"],
"cwd": "/path/to/script"
}
}
```
</Tab> */}
</Tabs>
## Advanced Features
### Hot Reloading
MCPHub supports hot reloading of server configurations:
{/* 1. **Config File Changes**: Automatically detects changes to `mcp_settings.json` */}
1. **Dashboard Updates**: Immediately applies changes made through the web interface
2. **API Updates**: Real-time updates via REST API calls
3. **Zero Downtime**: Graceful server restarts without affecting other servers
{/* ### Resource Limits
Control server resource usage:
```json
{
"resource-limited-server": {
"command": "memory-intensive-server",
"args": [],
"limits": {
"memory": "512MB",
"cpu": "50%",
"timeout": "30s"
}
}
}
``` */}
{/* ### Dependency Management
Handle server dependencies:
<AccordionGroup>
<Accordion title="Auto-installation">
MCPHub can automatically install missing packages:
```json
{
"auto-install-server": {
"command": "npx",
"args": ["-y", "package-that-might-not-exist"],
"autoInstall": true
}
}
```
</Accordion>
<Accordion title="Pre-installation Scripts">
Run setup scripts before starting servers:
```json
{
"setup-server": {
"preStart": ["npm install", "pip install -r requirements.txt"],
"command": "python",
"args": ["server.py"]
}
}
```
</Accordion>
</AccordionGroup> */}
## Troubleshooting
<AccordionGroup>
<Accordion title="Server Won't Start">
**Check the following:**
- Command is available in PATH
- All required environment variables are set
- Working directory exists and is accessible
- Network ports are not blocked
- Dependencies are installed
**Debug steps:**
1. Check server logs in the dashboard
2. Test command manually in terminal
3. Verify environment variable expansion
4. Check file permissions
</Accordion>
<Accordion title="Server Keeps Crashing">
**Common causes:**
- Invalid configuration parameters
- Missing API keys or credentials
- Resource limits exceeded
- Dependency conflicts
**Solutions:**
1. Review server logs for error messages
2. Test with minimal configuration
3. Verify all credentials and API keys
4. Check system resource availability
</Accordion>
<Accordion title="Tools Not Appearing">
**Possible issues:**
- Server not fully initialized
- Tool discovery timeout
- Communication protocol mismatch
- Server reporting errors
**Debug steps:**
1. Wait for server initialization to complete
2. Check server logs for tool registration messages
3. Test direct communication with server
4. Verify MCP protocol compatibility
</Accordion>
</AccordionGroup>
## Next Steps
<CardGroup cols={2}>
<Card title="Group Management" icon="users" href="/features/group-management">
Organize servers into logical groups
</Card>
<Card title="Smart Routing" icon="route" href="/features/smart-routing">
Set up AI-powered tool discovery
</Card>
<Card title="API Reference" icon="code" href="/api-reference/servers">
Server management API documentation
</Card>
<Card title="Configuration Guide" icon="cog" href="/configuration/mcp-settings">
Detailed configuration options
</Card>
</CardGroup>

View File

@@ -0,0 +1,795 @@
---
title: 'Smart Routing'
description: 'AI-powered tool discovery using vector semantic search'
---
## Overview
Smart Routing is MCPHub's intelligent tool discovery system that uses vector semantic search to automatically find the most relevant tools for any given task. Instead of manually specifying which tools to use, AI clients can describe what they want to accomplish, and Smart Routing will identify and provide access to the most appropriate tools.
## How Smart Routing Works
### 1. Tool Indexing
When servers start up, Smart Routing automatically:
- Discovers all available tools from MCP servers
- Extracts tool metadata (names, descriptions, parameters)
- Converts tool information to vector embeddings
- Stores embeddings in PostgreSQL with pgvector
### 2. Semantic Search
When a query is made:
- User queries are converted to vector embeddings
- Similarity search finds matching tools using cosine similarity
- Dynamic thresholds filter out irrelevant results
- Results are ranked by relevance score
### 3. Intelligent Filtering
Smart Routing applies several filters:
- **Relevance Threshold**: Only returns tools above similarity threshold
- **Context Awareness**: Considers conversation context
- **Tool Availability**: Ensures tools are currently accessible
- **Permission Filtering**: Respects user access permissions
### 4. Tool Execution
Found tools can be directly executed:
- Parameter validation ensures correct tool usage
- Error handling provides helpful feedback
- Response formatting maintains consistency
- Logging tracks tool usage for analytics
## Prerequisites
Smart Routing requires additional setup compared to basic MCPHub usage:
### Required Components
1. **PostgreSQL with pgvector**: Vector database for embeddings storage
2. **Embedding Service**: OpenAI API or compatible service
3. **Environment Configuration**: Proper configuration variables
{/* ### Quick Setup
<Tabs>
<Tab title="Docker Compose">
Use this `docker-compose.yml` for complete setup:
```yaml
version: '3.8'
services:
mcphub:
image: samanhappy/mcphub:latest
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://mcphub:password@postgres:5432/mcphub
- OPENAI_API_KEY=your_openai_api_key
- ENABLE_SMART_ROUTING=true
depends_on:
- postgres
volumes:
- ./mcp_settings.json:/app/mcp_settings.json
postgres:
image: pgvector/pgvector:pg16
environment:
- POSTGRES_DB=mcphub
- POSTGRES_USER=mcphub
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
postgres_data:
```
Start with:
```bash
docker-compose up -d
```
</Tab>
<Tab title="Manual Setup">
1. **Install PostgreSQL with pgvector**:
```bash
# Using Docker
docker run -d \
--name mcphub-postgres \
-e POSTGRES_DB=mcphub \
-e POSTGRES_USER=mcphub \
-e POSTGRES_PASSWORD=your_password \
-p 5432:5432 \
pgvector/pgvector:pg16
```
2. **Set Environment Variables**:
```bash
export DATABASE_URL="postgresql://mcphub:your_password@localhost:5432/mcphub"
export OPENAI_API_KEY="your_openai_api_key"
export ENABLE_SMART_ROUTING="true"
```
3. **Start MCPHub**:
```bash
mcphub
```
</Tab>
<Tab title="Kubernetes">
Deploy with these Kubernetes manifests:
```yaml
# postgres-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
spec:
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: pgvector/pgvector:pg16
env:
- name: POSTGRES_DB
value: mcphub
- name: POSTGRES_USER
value: mcphub
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
ports:
- containerPort: 5432
---
# mcphub-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcphub
spec:
selector:
matchLabels:
app: mcphub
template:
metadata:
labels:
app: mcphub
spec:
containers:
- name: mcphub
image: samanhappy/mcphub:latest
env:
- name: DATABASE_URL
value: "postgresql://mcphub:password@postgres:5432/mcphub"
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: openai-secret
key: api-key
- name: ENABLE_SMART_ROUTING
value: "true"
ports:
- containerPort: 3000
```
</Tab>
</Tabs>
## Configuration
### Environment Variables
Configure Smart Routing with these environment variables:
```bash
# Required
DATABASE_URL=postgresql://user:password@host:5432/database
OPENAI_API_KEY=your_openai_api_key
# Optional
ENABLE_SMART_ROUTING=true
EMBEDDING_MODEL=text-embedding-3-small
SIMILARITY_THRESHOLD=0.7
MAX_TOOLS_RETURNED=10
EMBEDDING_BATCH_SIZE=100
```
### Configuration Options
<AccordionGroup>
<Accordion title="Database Configuration">
```bash
# Full PostgreSQL connection string
DATABASE_URL=postgresql://username:password@host:port/database?schema=public
# SSL configuration for cloud databases
DATABASE_URL=postgresql://user:pass@host:5432/db?sslmode=require
# Connection pool settings
DATABASE_POOL_SIZE=20
DATABASE_TIMEOUT=30000
```
</Accordion>
<Accordion title="Embedding Service">
```bash
# OpenAI (default)
OPENAI_API_KEY=sk-your-api-key
EMBEDDING_MODEL=text-embedding-3-small
# Azure OpenAI
AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com
AZURE_OPENAI_API_KEY=your-api-key
AZURE_OPENAI_DEPLOYMENT=your-embedding-deployment
# Custom embedding service
EMBEDDING_SERVICE_URL=https://your-embedding-service.com
EMBEDDING_SERVICE_API_KEY=your-api-key
```
</Accordion>
<Accordion title="Search Parameters">
```bash
# Similarity threshold (0.0 to 1.0)
SIMILARITY_THRESHOLD=0.7
# Maximum tools to return
MAX_TOOLS_RETURNED=10
# Minimum query length for smart routing
MIN_QUERY_LENGTH=5
# Cache TTL for embeddings (seconds)
EMBEDDING_CACHE_TTL=3600
```
</Accordion>
</AccordionGroup> */}
## Using Smart Routing
### Smart Routing Endpoint
Access Smart Routing through the special `$smart` endpoint:
<Tabs>
<Tab title="HTTP MCP">
```
# Search across all servers
http://localhost:3000/mcp/$smart
# Search within a specific group
http://localhost:3000/mcp/$smart/{group}
```
</Tab>
<Tab title="SSE (Legacy)">
```
# Search across all servers
http://localhost:3000/sse/$smart
# Search within a specific group
http://localhost:3000/sse/$smart/{group}
```
</Tab>
</Tabs>
### Group-Scoped Smart Routing
Smart Routing now supports group-scoped searches, allowing you to limit tool discovery to servers within a specific group:
<AccordionGroup>
<Accordion title="Using Group-Scoped Smart Routing">
Connect your AI client to a group-specific Smart Routing endpoint:
```
http://localhost:3000/mcp/$smart/production
```
This endpoint will only search for tools within servers that belong to the "production" group.
**Benefits:**
- **Focused Results**: Only tools from relevant servers are returned
- **Better Performance**: Reduced search space for faster queries
- **Environment Isolation**: Keep development, staging, and production tools separate
- **Access Control**: Limit tool discovery based on user permissions
</Accordion>
<Accordion title="Example: Environment-Based Groups">
Create groups for different environments:
```bash
# Development environment
http://localhost:3000/mcp/$smart/development
# Staging environment
http://localhost:3000/mcp/$smart/staging
# Production environment
http://localhost:3000/mcp/$smart/production
```
Each endpoint will only return tools from servers in that specific environment group.
</Accordion>
<Accordion title="Example: Team-Based Groups">
Organize tools by team or department:
```bash
# Backend team tools
http://localhost:3000/mcp/$smart/backend-team
# Frontend team tools
http://localhost:3000/mcp/$smart/frontend-team
# DevOps team tools
http://localhost:3000/mcp/$smart/devops-team
```
This enables teams to have focused access to their relevant toolsets.
</Accordion>
<Accordion title="How It Works">
When using `$smart/{group}`:
1. The system identifies the specified group
2. Retrieves all servers belonging to that group
3. Filters the tool search to only those servers
4. Returns results scoped to the group's servers
If the group doesn't exist or has no servers, the search will return no results.
</Accordion>
</AccordionGroup>
{/* ### Basic Usage
Connect your AI client to the Smart Routing endpoint and make natural language requests:
```bash
# Example: Find tools for web scraping
curl -X POST http://localhost:3000/mcp/$smart \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/search",
"params": {
"query": "scrape website content and extract text"
}
}'
```
Response:
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "fetch_html",
"server": "fetch",
"description": "Fetch and parse HTML content from a URL",
"relevanceScore": 0.92,
"parameters": { ... }
},
{
"name": "playwright_navigate",
"server": "playwright",
"description": "Navigate to a web page and extract content",
"relevanceScore": 0.87,
"parameters": { ... }
}
]
}
}
``` */}
{/* ### Advanced Queries
Smart Routing supports various query types:
<AccordionGroup>
<Accordion title="Task-Based Queries">
```bash
# What you want to accomplish
curl -X POST http://localhost:3000/mcp/$smart \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/search",
"params": {
"query": "send a message to a slack channel"
}
}'
```
</Accordion>
<Accordion title="Domain-Specific Queries">
```bash
# Specific domain or technology
curl -X POST http://localhost:3000/mcp/$smart \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/search",
"params": {
"query": "database operations SQL queries"
}
}'
```
</Accordion>
<Accordion title="Action-Oriented Queries">
```bash
# Specific actions
curl -X POST http://localhost:3000/mcp/$smart \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/search",
"params": {
"query": "create file upload to github repository"
}
}'
```
</Accordion>
<Accordion title="Context-Aware Queries">
```bash
# Include context for better results
curl -X POST http://localhost:3000/mcp/$smart \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/search",
"params": {
"query": "automated testing web application",
"context": {
"project": "e-commerce website",
"technologies": ["React", "Node.js"],
"environment": "staging"
}
}
}'
```
</Accordion>
</AccordionGroup> */}
{/* ### Tool Execution
Once Smart Routing finds relevant tools, you can execute them directly:
```bash
# Execute a found tool
curl -X POST http://localhost:3000/mcp/$smart \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "fetch_html",
"arguments": {
"url": "https://example.com"
}
}
}'
``` */}
{/* ## Performance Optimization
### Embedding Cache
Smart Routing caches embeddings to improve performance:
```bash
# Configure cache settings
EMBEDDING_CACHE_TTL=3600 # Cache for 1 hour
EMBEDDING_CACHE_SIZE=10000 # Cache up to 10k embeddings
EMBEDDING_CACHE_CLEANUP=300 # Cleanup every 5 minutes
```
### Batch Processing
Tools are indexed in batches for efficiency:
```bash
# Batch size for embedding generation
EMBEDDING_BATCH_SIZE=100
# Concurrent embedding requests
EMBEDDING_CONCURRENCY=5
# Index update frequency
INDEX_UPDATE_INTERVAL=3600 # Re-index every hour
```
### Database Optimization
Optimize PostgreSQL for vector operations:
```sql
-- Create indexes for better performance
CREATE INDEX ON tool_embeddings USING hnsw (embedding vector_cosine_ops);
-- Adjust PostgreSQL settings
ALTER SYSTEM SET shared_preload_libraries = 'vector';
ALTER SYSTEM SET max_connections = 200;
ALTER SYSTEM SET shared_buffers = '256MB';
ALTER SYSTEM SET effective_cache_size = '1GB';
```
## Monitoring and Analytics
### Smart Routing Metrics
Monitor Smart Routing performance:
```bash
# Get Smart Routing statistics
curl http://localhost:3000/api/smart-routing/stats \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
Response includes:
- Query count and frequency
- Average response time
- Embedding cache hit rate
- Most popular tools
- Query patterns
### Tool Usage Analytics
Track which tools are found and used:
```bash
# Get tool usage analytics
curl http://localhost:3000/api/smart-routing/analytics \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
Metrics include:
- Tool discovery rates
- Execution success rates
- User satisfaction scores
- Query-to-execution conversion
### Performance Monitoring
Monitor system performance:
```bash
# Database performance
curl http://localhost:3000/api/smart-routing/db-stats \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
# Embedding service status
curl http://localhost:3000/api/smart-routing/embedding-stats \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
## Advanced Features
### Custom Embeddings
Use custom embedding models:
```bash
# Hugging Face models
EMBEDDING_SERVICE=huggingface
HUGGINGFACE_MODEL=sentence-transformers/all-MiniLM-L6-v2
HUGGINGFACE_API_KEY=your_api_key
# Local embedding service
EMBEDDING_SERVICE=local
EMBEDDING_SERVICE_URL=http://localhost:8080/embeddings
```
### Query Enhancement
Enhance queries for better results:
```json
{
"queryEnhancement": {
"enabled": true,
"expandAcronyms": true,
"addSynonyms": true,
"contextualExpansion": true
}
}
```
### Result Filtering
Filter results based on criteria:
```json
{
"resultFiltering": {
"minRelevanceScore": 0.7,
"maxResults": 10,
"preferredServers": ["fetch", "playwright"],
"excludeServers": ["deprecated-server"]
}
}
```
### Feedback Learning
Improve results based on user feedback:
```bash
# Provide feedback on search results
curl -X POST http://localhost:3000/api/smart-routing/feedback \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"queryId": "search-123",
"toolName": "fetch_html",
"rating": 5,
"successful": true,
"comments": "Perfect tool for the task"
}'
``` */}
## Troubleshooting
<AccordionGroup>
<Accordion title="Database Connection Issues">
**Symptoms:**
- Smart Routing not available
- Database connection errors
- Embedding storage failures
**Solutions:**
1. Verify PostgreSQL is running
2. Check DATABASE_URL format
3. Ensure pgvector extension is installed
4. Test connection manually:
```bash
psql $DATABASE_URL -c "SELECT 1;"
```
</Accordion>
<Accordion title="Embedding Service Problems">
**Symptoms:**
- Tool indexing failures
- Query processing errors
- API rate limit errors
**Solutions:**
1. Verify API key validity
2. Check network connectivity
3. Monitor rate limits
4. Test embedding service:
```bash
curl -X POST https://api.openai.com/v1/embeddings \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"input": "test", "model": "text-embedding-3-small"}'
```
</Accordion>
<Accordion title="Poor Search Results">
**Symptoms:**
- Irrelevant tools returned
- Low relevance scores
- Missing expected tools
**Solutions:**
1. Adjust similarity threshold
2. Re-index tools with better descriptions
3. Use more specific queries
4. Check tool metadata quality
```bash
# Re-index all tools
curl -X POST http://localhost:3000/api/smart-routing/reindex \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
</Accordion>
<Accordion title="Performance Issues">
**Symptoms:**
- Slow query responses
- High database load
- Memory usage spikes
**Solutions:**
1. Optimize database configuration
2. Increase cache sizes
3. Reduce batch sizes
4. Monitor system resources
```bash
# Check system performance
curl http://localhost:3000/api/smart-routing/performance \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
</Accordion>
</AccordionGroup>
## Best Practices
### Query Writing
<Tip>
**Be Descriptive**: Use specific, descriptive language in queries for better tool matching.
</Tip>
<Tip>
**Include Context**: Provide relevant context about your task or domain for more accurate results.
</Tip>
<Tip>**Use Natural Language**: Write queries as you would describe the task to a human.</Tip>
### Tool Descriptions
<Warning>
**Quality Metadata**: Ensure MCP servers provide high-quality tool descriptions and metadata.
</Warning>
<Warning>**Regular Updates**: Keep tool descriptions current as functionality evolves.</Warning>
<Warning>
**Consistent Naming**: Use consistent naming conventions across tools and servers.
</Warning>
### System Maintenance
<Info>**Regular Re-indexing**: Periodically re-index tools to ensure embedding quality.</Info>
<Info>**Monitor Performance**: Track query patterns and optimize based on usage.</Info>
<Info>
**Update Models**: Consider updating to newer embedding models as they become available.
</Info>
## Next Steps
<CardGroup cols={2}>
<Card title="Authentication" icon="shield" href="/features/authentication">
User management and access control
</Card>
<Card title="Monitoring" icon="chart-line" href="/features/monitoring">
System monitoring and analytics
</Card>
<Card title="API Reference" icon="code" href="/api-reference/smart-routing">
Complete Smart Routing API documentation
</Card>
<Card title="Configuration" icon="cog" href="/configuration/environment-variables">
Advanced configuration options
</Card>
</CardGroup>

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

BIN
docs/images/hero-dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

BIN
docs/images/hero-light.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

95
docs/index.mdx Normal file
View File

@@ -0,0 +1,95 @@
---
title: MCPHub
description: 'The Unified Hub for Model Context Protocol (MCP) Servers'
---
{/* <img className="block dark:hidden" src="/images/hero-light.png" alt="Hero Light" />
<img className="hidden dark:block" src="/images/hero-dark.png" alt="Hero Dark" /> */}
# Welcome to MCPHub
MCPHub makes it easy to manage and scale multiple MCP (Model Context Protocol) servers by organizing them into flexible Streamable HTTP (SSE) endpoints—supporting access to all servers, individual servers, or logical server groups.
## Key Features
<CardGroup cols={2}>
<Card title="Unified Management" icon="server" href="/features/server-management">
Centrally manage multiple MCP servers with hot-swappable configuration
</Card>
<Card title="Group Management" icon="users" href="/features/group-management">
Organize servers into logical groups for streamlined access control
</Card>
<Card title="Smart Routing" icon="route" href="/features/smart-routing">
AI-powered tool discovery using vector semantic search
</Card>
<Card title="Real-time Monitoring" icon="chart-line" href="/features/monitoring">
Monitor server status and performance from a unified dashboard
</Card>
</CardGroup>
## Quick Start
Get MCPHub running in minutes with Docker:
```bash
docker run -p 3000:3000 samanhappy/mcphub
```
Or with custom configuration:
```bash
docker run -p 3000:3000 -v $(pwd)/mcp_settings.json:/app/mcp_settings.json samanhappy/mcphub
```
Access the dashboard at `http://localhost:3000` with default credentials:
- Username: `admin`
- Password: `admin123`
## Core Concepts
### MCP Endpoints
MCPHub provides multiple ways to access your MCP servers:
- **Unified Access**: `http://localhost:3000/mcp` - Access all servers
- **Group Access**: `http://localhost:3000/mcp/{group}` - Access specific groups
- **Server Access**: `http://localhost:3000/mcp/{server}` - Access individual servers
- **Smart Routing**: `http://localhost:3000/mcp/$smart` - AI-powered tool discovery
### Protocol Support
- **HTTP MCP**: Modern streamable HTTP interface (recommended)
- **SSE**: Server-Sent Events for legacy compatibility
- **stdio**: Native MCP protocol for server communication
## Getting Started
<CardGroup cols={2}>
<Card title="Quick Start Guide" icon="rocket" href="/quickstart">
Get MCPHub running in 5 minutes
</Card>
<Card title="Installation Guide" icon="download" href="/installation">
Detailed installation instructions for all platforms
</Card>
<Card title="Configuration" icon="cog" href="/configuration/mcp-settings">
Learn how to configure your MCP servers
</Card>
<Card title="API Reference" icon="code" href="/api-reference/introduction">
Complete API documentation
</Card>
</CardGroup>
## Community & Support
<CardGroup cols={3}>
<Card title="GitHub" icon="github" href="https://github.com/samanhappy/mcphub">
Source code and issue tracking
</Card>
<Card title="Discord" icon="discord" href="https://discord.gg/qMKNsn5Q">
Join our community discussions
</Card>
<Card title="Sponsor" icon="heart" href="https://ko-fi.com/samanhappy">
Support the project development
</Card>
</CardGroup>

595
docs/installation.mdx Normal file
View File

@@ -0,0 +1,595 @@
---
title: 'Installation Guide'
description: 'Detailed installation instructions for all platforms'
---
## Prerequisites
Before installing MCPHub, ensure you have the following prerequisites:
- **Node.js** 18+ (for local development)
- **Docker** (recommended for production)
- **pnpm** (for local development)
Optional for Smart Routing:
- **PostgreSQL** with pgvector extension
- **OpenAI API Key** or compatible embedding service
## Installation Methods
<Tabs>
<Tab title="Docker (Recommended)">
### Docker Installation
Docker is the recommended way to deploy MCPHub in production.
#### 1. Basic Installation
```bash
# Pull the latest image
docker pull samanhappy/mcphub:latest
# Run with default settings
docker run -d \
--name mcphub \
-p 3000:3000 \
samanhappy/mcphub:latest
```
#### 2. With Custom Configuration
```bash
# Create your configuration file
cat > mcp_settings.json << 'EOF'
{
"mcpServers": {
"fetch": {
"command": "uvx",
"args": ["mcp-server-fetch"]
},
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest", "--headless"]
}
}
}
EOF
# Run with mounted config
docker run -d \
--name mcphub \
-p 3000:3000 \
-v $(pwd)/mcp_settings.json:/app/mcp_settings.json \
samanhappy/mcphub:latest
```
#### 3. With Environment Variables
```bash
docker run -d \
--name mcphub \
-p 3000:3000 \
-e PORT=3000 \
-e BASE_PATH="" \
samanhappy/mcphub:latest
```
#### 4. Docker Compose
Create a `docker-compose.yml` file:
```yaml
version: '3.8'
services:
mcphub:
image: samanhappy/mcphub:latest
ports:
- "3000:3000"
volumes:
- ./mcp_settings.json:/app/mcp_settings.json
environment:
- PORT=3000
- BASE_PATH=""
- REQUEST_TIMEOUT=60000
restart: unless-stopped
# Optional: PostgreSQL for Smart Routing
postgres:
image: pgvector/pgvector:pg16
environment:
POSTGRES_DB: mcphub
POSTGRES_USER: mcphub
POSTGRES_PASSWORD: mcphub_password
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
postgres_data:
```
Run with:
```bash
docker-compose up -d
```
</Tab>
<Tab title="npm Package">
### npm Package Installation
Install MCPHub as a global npm package:
#### 1. Global Installation
```bash
# Install globally
npm install -g @samanhappy/mcphub
# Or with yarn
yarn global add @samanhappy/mcphub
# Or with pnpm
pnpm add -g @samanhappy/mcphub
```
#### 2. Running MCPHub
```bash
# Run with default settings
mcphub
# Run with custom port
PORT=8080 mcphub
```
{/* #### 3. Local Installation
You can also install MCPHub locally in a project:
```bash
# Create a new directory
mkdir my-mcphub
cd my-mcphub
# Initialize package.json
npm init -y
# Install MCPHub locally
npm install @samanhappy/mcphub
# Create a start script
echo '#!/bin/bash\nnpx mcphub' > start.sh
chmod +x start.sh
# Run MCPHub
./start.sh
``` */}
</Tab>
<Tab title="Local Development">
### Local Development Setup
For development, customization, or contribution:
#### 1. Clone Repository
```bash
# Clone the repository
git clone https://github.com/samanhappy/mcphub.git
cd mcphub
```
#### 2. Install Dependencies
```bash
# Install dependencies with pnpm (recommended)
pnpm install
# Or with npm
npm install
# Or with yarn
yarn install
```
#### 3. Development Mode
```bash
# Start both backend and frontend in development mode
pnpm dev
# This will start:
# - Backend on http://localhost:3001
# - Frontend on http://localhost:5173
# - Frontend proxies API calls to backend
```
#### 4. Build for Production
```bash
# Build both backend and frontend
pnpm build
# Start production server
pnpm start
```
#### 5. Development Scripts
```bash
# Backend only (for API development)
pnpm backend:dev
# Frontend only (when backend is running separately)
pnpm frontend:dev
# Run tests
pnpm test
# Lint code
pnpm lint
# Format code
pnpm format
```
<Note>
On Windows, you may need to run backend and frontend separately:
```bash
# Terminal 1: Backend
pnpm backend:dev
# Terminal 2: Frontend
pnpm frontend:dev
```
</Note>
</Tab>
<Tab title="Kubernetes">
### Kubernetes Deployment
Deploy MCPHub on Kubernetes with these manifests:
#### 1. ConfigMap for Settings
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mcphub-config
data:
mcp_settings.json: |
{
"mcpServers": {
"fetch": {
"command": "uvx",
"args": ["mcp-server-fetch"]
},
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest", "--headless"]
}
}
}
```
#### 2. Deployment
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcphub
spec:
replicas: 1
selector:
matchLabels:
app: mcphub
template:
metadata:
labels:
app: mcphub
spec:
initContainers:
- name: prepare-config
image: busybox:1.28
command:
[
"sh",
"-c",
"cp /config-ro/mcp_settings.json /etc/mcphub/mcp_settings.json",
]
volumeMounts:
- name: config
mountPath: /config-ro
readOnly: true
- name: app-storage
mountPath: /etc/mcphub
containers:
- name: mcphub
image: samanhappy/mcphub:latest
ports:
- containerPort: 3000
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
env:
- name: PORT
value: "3000"
- name: MCPHUB_SETTING_PATH
value: /etc/mcphub/mcp_settings.json
volumeMounts:
- name: app-storage
mountPath: /etc/mcphub
volumes:
- name: config
configMap:
name: mcphub-config
- name: app-storage
emptyDir: {}
```
#### 3. Service
```yaml
apiVersion: v1
kind: Service
metadata:
name: mcphub-service
spec:
selector:
app: mcphub
ports:
- port: 80
targetPort: 3000
type: ClusterIP
```
#### 4. Ingress (Optional)
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mcphub-ingress
annotations:
nginx.ingress.kubernetes.io/proxy-buffering: "off"
spec:
rules:
- host: mcphub.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: mcphub-service
port:
number: 80
```
Deploy with:
```bash
kubectl apply -f mcphub-configmap.yaml
kubectl apply -f mcphub-deployment.yaml
kubectl apply -f mcphub-service.yaml
kubectl apply -f mcphub-ingress.yaml
```
</Tab>
</Tabs>
## Smart Routing Setup (Optional)
Smart Routing provides AI-powered tool discovery using vector semantic search.
### Prerequisites
1. **PostgreSQL with pgvector**
2. **OpenAI API Key** (or compatible embedding service)
### Database Setup
<Tabs>
<Tab title="Docker PostgreSQL">
```bash
# Run PostgreSQL with pgvector
docker run -d \
--name mcphub-postgres \
-e POSTGRES_DB=mcphub \
-e POSTGRES_USER=mcphub \
-e POSTGRES_PASSWORD=your_password \
-p 5432:5432 \
pgvector/pgvector:pg16
```
</Tab>
<Tab title="Existing PostgreSQL">
If you have an existing PostgreSQL instance:
```sql
-- Connect to your PostgreSQL instance
-- Create database
CREATE DATABASE mcphub;
-- Connect to the mcphub database
\c mcphub;
-- Enable pgvector extension
CREATE EXTENSION IF NOT EXISTS vector;
```
</Tab>
<Tab title="Cloud PostgreSQL">
For cloud providers (AWS RDS, Google Cloud SQL, etc.):
1. Enable the pgvector extension in your cloud provider's console
2. Create a database named `mcphub`
3. Note down the connection details
</Tab>
</Tabs>
{/* ### Environment Configuration
Set the following environment variables:
```bash
# Database connection
DATABASE_URL=postgresql://mcphub:your_password@localhost:5432/mcphub
# OpenAI API for embeddings
OPENAI_API_KEY=your_openai_api_key
# Optional: Custom embedding model
EMBEDDING_MODEL=text-embedding-3-small
# Optional: Enable smart routing
ENABLE_SMART_ROUTING=true
``` */}
## Verification
After installation, verify MCPHub is working:
{/* ### 1. Health Check
```bash
curl http://localhost:3000/api/health
```
Expected response:
```json
{
"status": "ok",
"version": "x.x.x",
"uptime": 123
}
``` */}
### Dashboard Access
Open your browser and navigate to:
```
http://localhost:3000
```
{/* ### 3. API Test
```bash
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}'
``` */}
## Troubleshooting
<AccordionGroup>
<Accordion title="Docker Issues">
**Port already in use:**
```bash
# Check what's using port 3000
lsof -i :3000
# Use a different port
docker run -p 8080:3000 samanhappy/mcphub
```
**Container won't start:**
```bash
# Check container logs
docker logs mcphub
# Run interactively for debugging
docker run -it --rm samanhappy/mcphub /bin/bash
```
</Accordion>
<Accordion title="npm Installation Issues">
**Permission errors:**
```bash
# Use npx instead of global install
npx @samanhappy/mcphub
# Or fix npm permissions
npm config set prefix ~/.npm-global
export PATH=~/.npm-global/bin:$PATH
```
**Node version issues:**
```bash
# Check Node version
node --version
# Install Node 18+ using nvm
nvm install 18
nvm use 18
```
</Accordion>
<Accordion title="Network Issues">
**Can't access dashboard:**
- Check if MCPHub is running: `ps aux | grep mcphub`
- Verify port binding: `netstat -tlnp | grep 3000`
- Check firewall settings
- Try accessing via `127.0.0.1:3000` instead of `localhost:3000`
**AI clients can't connect:**
- Ensure the endpoint URL is correct
- Check if MCPHub is behind a proxy
- Verify network policies in Kubernetes/Docker environments
</Accordion>
<Accordion title="Smart Routing Issues">
**Database connection failed:**
```bash
# Test database connection
psql $DATABASE_URL -c "SELECT 1;"
# Check if pgvector is installed
psql $DATABASE_URL -c "CREATE EXTENSION IF NOT EXISTS vector;"
```
**Embedding service errors:**
- Verify OpenAI API key is valid
- Check internet connectivity
- Monitor rate limits
</Accordion>
</AccordionGroup>
## Next Steps
<CardGroup cols={2}>
<Card title="Configuration" icon="cog" href="/configuration/mcp-settings">
Configure your MCP servers and settings
</Card>
<Card title="Quick Start" icon="rocket" href="/quickstart">
Get up and running in 5 minutes
</Card>
<Card title="Server Management" icon="server" href="/features/server-management">
Learn how to manage your MCP servers
</Card>
<Card title="API Reference" icon="code" href="/api-reference/introduction">
Explore the complete API documentation
</Card>
</CardGroup>

27
docs/logo/dark.svg Normal file
View File

@@ -0,0 +1,27 @@
<svg width="320" height="80" viewBox="0 0 320 80" xmlns="http://www.w3.org/2000/svg">
<!-- Background with subtle gradient -->
<defs>
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#1e3a8a;stop-opacity:0.1" />
<stop offset="100%" style="stop-color:#3b82f6;stop-opacity:0.05" />
</linearGradient>
<linearGradient id="textGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#1e40af" />
<stop offset="50%" style="stop-color:#3b82f6" />
<stop offset="100%" style="stop-color:#1e40af" />
</linearGradient>
<linearGradient id="hubGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#059669" />
<stop offset="100%" style="stop-color:#10b981" />
</linearGradient>
</defs>
<!-- Background (transparent) -->
<!-- Text: MCPHub as one word -->
<text x="5" y="46" font-family="Arial, sans-serif" font-size="64" font-weight="bold" dominant-baseline="middle" text-anchor="start">
<tspan fill="url(#textGradient)">MCP</tspan><tspan fill="url(#hubGradient)">Hub</tspan>
</text>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

27
docs/logo/light.svg Normal file
View File

@@ -0,0 +1,27 @@
<svg width="320" height="80" viewBox="0 0 320 80" xmlns="http://www.w3.org/2000/svg">
<!-- Background with subtle gradient -->
<defs>
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#1e3a8a;stop-opacity:0.1" />
<stop offset="100%" style="stop-color:#3b82f6;stop-opacity:0.05" />
</linearGradient>
<linearGradient id="textGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#1e40af" />
<stop offset="50%" style="stop-color:#3b82f6" />
<stop offset="100%" style="stop-color:#1e40af" />
</linearGradient>
<linearGradient id="hubGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#059669" />
<stop offset="100%" style="stop-color:#10b981" />
</linearGradient>
</defs>
<!-- Background (transparent) -->
<!-- Text: MCPHub as one word -->
<text x="5" y="46" font-family="Arial, sans-serif" font-size="64" font-weight="bold" dominant-baseline="middle" text-anchor="start">
<tspan fill="url(#textGradient)">MCP</tspan><tspan fill="url(#hubGradient)">Hub</tspan>
</text>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,169 @@
# OAuth 动态客户端注册实现总结
## 概述
成功为 MCPHub 的 OAuth 2.0 授权服务器添加了 RFC 7591 标准的动态客户端注册功能。此功能允许 OAuth 客户端在运行时自动注册,无需管理员手动配置。
## 实现的功能
### 1. 核心端点
#### POST /oauth/register - 注册新客户端
- 公开端点,支持动态客户端注册
- 自动生成 client_id 和可选的 client_secret
- 返回 registration_access_token 用于后续管理
- 支持 PKCE 流程token_endpoint_auth_method: "none"
#### GET /oauth/register/:clientId - 读取客户端配置
- 需要 registration_access_token 认证
- 返回完整的客户端元数据
#### PUT /oauth/register/:clientId - 更新客户端配置
- 需要 registration_access_token 认证
- 支持更新 redirect_uris、scopes、metadata 等
#### DELETE /oauth/register/:clientId - 删除客户端注册
- 需要 registration_access_token 认证
- 删除客户端并清理相关 tokens
### 2. 配置选项
`mcp_settings.json` 中添加:
```json
{
"systemConfig": {
"oauthServer": {
"enabled": true,
"dynamicRegistration": {
"enabled": true,
"allowedGrantTypes": ["authorization_code", "refresh_token"],
"requiresAuthentication": false
}
}
}
}
```
### 3. 客户端元数据支持
实现了 RFC 7591 定义的完整客户端元数据:
- `application_type`: "web" 或 "native"
- `response_types`: OAuth 响应类型数组
- `token_endpoint_auth_method`: 认证方法
- `contacts`: 联系邮箱数组
- `logo_uri`: 客户端 logo URL
- `client_uri`: 客户端主页 URL
- `policy_uri`: 隐私政策 URL
- `tos_uri`: 服务条款 URL
- `jwks_uri`: JSON Web Key Set URL
- `jwks`: 内联 JSON Web Key Set
### 4. 安全特性
- **Registration Access Token**: 每个注册的客户端获得唯一的访问令牌
- **Token 过期**: Registration tokens 30 天后过期
- **HTTPS 验证**: Redirect URIs 必须使用 HTTPSlocalhost 除外)
- **Scope 验证**: 只允许配置中定义的 scopes
- **Grant Type 限制**: 只允许配置中定义的 grant types
## 文件变更
### 新增文件
1. `src/controllers/oauthDynamicRegistrationController.ts` - 动态注册控制器
2. `examples/oauth-dynamic-registration-config.json` - 配置示例
### 修改文件
1. `src/types/index.ts` - 添加元数据字段到 IOAuthClient 和 OAuthServerConfig
2. `src/routes/index.ts` - 注册新的动态注册端点
3. `src/controllers/oauthServerController.ts` - 元数据端点包含 registration_endpoint
4. `docs/oauth-server.md` - 添加完整的动态注册文档
## 使用示例
### 注册新客户端
```bash
curl -X POST http://localhost:3000/oauth/register \
-H "Content-Type: application/json" \
-d '{
"client_name": "My Application",
"redirect_uris": ["https://example.com/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"],
"scope": "read write",
"token_endpoint_auth_method": "none",
"logo_uri": "https://example.com/logo.png",
"client_uri": "https://example.com",
"contacts": ["admin@example.com"]
}'
```
响应:
```json
{
"client_id": "a1b2c3d4e5f6g7h8",
"client_name": "My Application",
"redirect_uris": ["https://example.com/callback"],
"registration_access_token": "reg_token_xyz123",
"registration_client_uri": "http://localhost:3000/oauth/register/a1b2c3d4e5f6g7h8",
"client_id_issued_at": 1699200000
}
```
### 读取客户端配置
```bash
curl http://localhost:3000/oauth/register/CLIENT_ID \
-H "Authorization: Bearer REGISTRATION_ACCESS_TOKEN"
```
### 更新客户端
```bash
curl -X PUT http://localhost:3000/oauth/register/CLIENT_ID \
-H "Authorization: Bearer REGISTRATION_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"client_name": "Updated Name",
"redirect_uris": ["https://example.com/callback", "https://example.com/callback2"]
}'
```
### 删除客户端
```bash
curl -X DELETE http://localhost:3000/oauth/register/CLIENT_ID \
-H "Authorization: Bearer REGISTRATION_ACCESS_TOKEN"
```
## 测试结果
✅ 所有 180 个测试通过
✅ TypeScript 编译成功
✅ 代码覆盖率维持在合理水平
✅ 与现有功能完全兼容
## RFC 合规性
完全遵循以下 RFC 标准:
- **RFC 7591**: OAuth 2.0 Dynamic Client Registration Protocol
- **RFC 8414**: OAuth 2.0 Authorization Server Metadata
- **RFC 7636**: Proof Key for Code Exchange (PKCE)
- **RFC 9728**: OAuth 2.0 Protected Resource Metadata
## 下一步建议
1. **持久化存储**: 当前 registration tokens 存储在内存中,生产环境应使用数据库
2. **速率限制**: 添加注册端点的速率限制以防止滥用
3. **客户端证明**: 考虑添加软件声明software_statement支持
4. **审计日志**: 记录所有注册、更新和删除操作
5. **通知机制**: 在客户端注册时通知管理员(可选)
## 兼容性
- 与 ChatGPT Web 完全兼容
- 支持所有标准 OAuth 2.0 客户端库
- 向后兼容现有的手动客户端配置方式

538
docs/oauth-server.md Normal file
View File

@@ -0,0 +1,538 @@
# OAuth 2.0 Authorization Server
MCPHub can act as an OAuth 2.0 authorization server, allowing external applications like ChatGPT Web to securely authenticate and access your MCP servers.
## Overview
The OAuth 2.0 authorization server feature enables MCPHub to:
- Provide standard OAuth 2.0 authentication flows
- Issue and manage access tokens for external clients
- Support secure authorization without exposing user credentials
- Enable integration with services that require OAuth (like ChatGPT Web)
## Configuration
### Enable OAuth Server
Add the following configuration to your `mcp_settings.json`:
```json
{
"systemConfig": {
"oauthServer": {
"enabled": true,
"accessTokenLifetime": 3600,
"refreshTokenLifetime": 1209600,
"authorizationCodeLifetime": 300,
"requireClientSecret": false,
"allowedScopes": ["read", "write"],
"requireState": false
}
}
}
```
### Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enabled` | boolean | `false` | Enable/disable OAuth authorization server |
| `accessTokenLifetime` | number | `3600` | Access token lifetime in seconds (1 hour) |
| `refreshTokenLifetime` | number | `1209600` | Refresh token lifetime in seconds (14 days) |
| `authorizationCodeLifetime` | number | `300` | Authorization code lifetime in seconds (5 minutes) |
| `requireClientSecret` | boolean | `false` | Whether client secret is required (set to false for PKCE) |
| `allowedScopes` | string[] | `["read", "write"]` | List of allowed OAuth scopes |
| `requireState` | boolean | `false` | When `true`, rejects authorization requests that omit the `state` parameter |
## OAuth Clients
### Creating OAuth Clients
#### Via API (Recommended)
Create an OAuth client using the API:
```bash
curl -X POST http://localhost:3000/api/oauth/clients \
-H "Content-Type: application/json" \
-H "x-auth-token: YOUR_JWT_TOKEN" \
-d '{
"name": "My Application",
"redirectUris": ["https://example.com/callback"],
"grants": ["authorization_code", "refresh_token"],
"scopes": ["read", "write"],
"requireSecret": false
}'
```
Response:
```json
{
"success": true,
"message": "OAuth client created successfully",
"client": {
"clientId": "a1b2c3d4e5f6g7h8",
"clientSecret": null,
"name": "My Application",
"redirectUris": ["https://example.com/callback"],
"grants": ["authorization_code", "refresh_token"],
"scopes": ["read", "write"],
"owner": "admin"
}
}
```
**Important**: If `requireSecret` is true, the `clientSecret` will be shown only once. Save it securely!
#### Via Configuration File
Alternatively, add OAuth clients directly to `mcp_settings.json`:
```json
{
"oauthClients": [
{
"clientId": "my-app-client",
"clientSecret": "optional-secret-for-confidential-clients",
"name": "My Application",
"redirectUris": ["https://example.com/callback"],
"grants": ["authorization_code", "refresh_token"],
"scopes": ["read", "write"],
"owner": "admin"
}
]
}
```
### Managing OAuth Clients
#### List All Clients
```bash
curl http://localhost:3000/api/oauth/clients \
-H "x-auth-token: YOUR_JWT_TOKEN"
```
#### Get Specific Client
```bash
curl http://localhost:3000/api/oauth/clients/CLIENT_ID \
-H "x-auth-token: YOUR_JWT_TOKEN"
```
#### Update Client
```bash
curl -X PUT http://localhost:3000/api/oauth/clients/CLIENT_ID \
-H "Content-Type: application/json" \
-H "x-auth-token: YOUR_JWT_TOKEN" \
-d '{
"name": "Updated Name",
"redirectUris": ["https://example.com/callback", "https://example.com/callback2"]
}'
```
#### Delete Client
```bash
curl -X DELETE http://localhost:3000/api/oauth/clients/CLIENT_ID \
-H "x-auth-token: YOUR_JWT_TOKEN"
```
#### Regenerate Client Secret
```bash
curl -X POST http://localhost:3000/api/oauth/clients/CLIENT_ID/regenerate-secret \
-H "x-auth-token: YOUR_JWT_TOKEN"
```
## OAuth Flow
MCPHub supports the OAuth 2.0 Authorization Code flow with PKCE (Proof Key for Code Exchange).
### 1. Authorization Request
The client application redirects the user to the authorization endpoint:
```
GET /oauth/authorize?
client_id=CLIENT_ID&
redirect_uri=REDIRECT_URI&
response_type=code&
scope=read%20write&
state=RANDOM_STATE&
code_challenge=CODE_CHALLENGE&
code_challenge_method=S256
```
Parameters:
- `client_id`: OAuth client ID
- `redirect_uri`: Redirect URI (must match registered URI)
- `response_type`: Must be `code`
- `scope`: Space-separated list of scopes (e.g., `read write`)
- `state`: Random string to prevent CSRF attacks
- `code_challenge`: PKCE code challenge (optional but recommended)
- `code_challenge_method`: PKCE method (`S256` or `plain`)
### 2. User Authorization
The user is presented with a consent page showing:
- Application name
- Requested scopes
- Approve/Deny buttons
If the user approves, they are redirected to the redirect URI with an authorization code:
```
https://example.com/callback?code=AUTHORIZATION_CODE&state=RANDOM_STATE
```
### 3. Token Exchange
The client exchanges the authorization code for an access token:
```bash
curl -X POST http://localhost:3000/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=AUTHORIZATION_CODE" \
-d "redirect_uri=REDIRECT_URI" \
-d "client_id=CLIENT_ID" \
-d "code_verifier=CODE_VERIFIER"
```
Response:
```json
{
"access_token": "ACCESS_TOKEN",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "REFRESH_TOKEN",
"scope": "read write"
}
```
### 4. Using Access Token
Use the access token to make authenticated requests:
```bash
curl http://localhost:3000/api/servers \
-H "Authorization: Bearer ACCESS_TOKEN"
```
### 5. Refreshing Token
When the access token expires, use the refresh token to get a new one:
```bash
curl -X POST http://localhost:3000/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "refresh_token=REFRESH_TOKEN" \
-d "client_id=CLIENT_ID"
```
## PKCE (Proof Key for Code Exchange)
PKCE is a security extension to OAuth 2.0 that prevents authorization code interception attacks. It's especially important for public clients (mobile apps, SPAs).
### Generating PKCE Parameters
1. Generate a code verifier (random string):
```javascript
const codeVerifier = crypto.randomBytes(32).toString('base64url');
```
2. Generate code challenge from verifier:
```javascript
const codeChallenge = crypto
.createHash('sha256')
.update(codeVerifier)
.digest('base64url');
```
3. Include in authorization request:
- `code_challenge`: The generated challenge
- `code_challenge_method`: `S256`
4. Include in token request:
- `code_verifier`: The original verifier
## OAuth Scopes
MCPHub supports the following default scopes:
| Scope | Description |
|-------|-------------|
| `read` | Read access to MCP servers and tools |
| `write` | Execute tools and modify MCP server configurations |
You can customize allowed scopes in the `oauthServer.allowedScopes` configuration.
## Dynamic Client Registration (RFC 7591)
MCPHub supports RFC 7591 Dynamic Client Registration, allowing OAuth clients to register themselves programmatically without manual configuration.
### Enable Dynamic Registration
Add to your `mcp_settings.json`:
```json
{
"systemConfig": {
"oauthServer": {
"enabled": true,
"dynamicRegistration": {
"enabled": true,
"allowedGrantTypes": ["authorization_code", "refresh_token"],
"requiresAuthentication": false
}
}
}
}
```
### Register a New Client
**POST /oauth/register**
```bash
curl -X POST http://localhost:3000/oauth/register \
-H "Content-Type: application/json" \
-d '{
"client_name": "My Application",
"redirect_uris": ["https://example.com/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"],
"scope": "read write",
"token_endpoint_auth_method": "none"
}'
```
Response:
```json
{
"client_id": "a1b2c3d4e5f6g7h8",
"client_name": "My Application",
"redirect_uris": ["https://example.com/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"],
"scope": "read write",
"token_endpoint_auth_method": "none",
"registration_access_token": "reg_token_xyz123",
"registration_client_uri": "http://localhost:3000/oauth/register/a1b2c3d4e5f6g7h8",
"client_id_issued_at": 1699200000
}
```
**Important:** Save the `registration_access_token` - it's required to read, update, or delete the client registration.
### Read Client Configuration
**GET /oauth/register/:clientId**
```bash
curl http://localhost:3000/oauth/register/CLIENT_ID \
-H "Authorization: Bearer REGISTRATION_ACCESS_TOKEN"
```
### Update Client Configuration
**PUT /oauth/register/:clientId**
```bash
curl -X PUT http://localhost:3000/oauth/register/CLIENT_ID \
-H "Authorization: Bearer REGISTRATION_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"client_name": "Updated Application Name",
"redirect_uris": ["https://example.com/callback", "https://example.com/callback2"]
}'
```
### Delete Client Registration
**DELETE /oauth/register/:clientId**
```bash
curl -X DELETE http://localhost:3000/oauth/register/CLIENT_ID \
-H "Authorization: Bearer REGISTRATION_ACCESS_TOKEN"
```
### Optional Client Metadata
When registering a client, you can include additional metadata:
- `application_type`: `"web"` or `"native"` (default: `"web"`)
- `contacts`: Array of email addresses
- `logo_uri`: URL of client logo
- `client_uri`: URL of client homepage
- `policy_uri`: URL of privacy policy
- `tos_uri`: URL of terms of service
- `jwks_uri`: URL of JSON Web Key Set
- `jwks`: Inline JSON Web Key Set
Example:
```json
{
"client_name": "My Application",
"redirect_uris": ["https://example.com/callback"],
"application_type": "web",
"contacts": ["admin@example.com"],
"logo_uri": "https://example.com/logo.png",
"client_uri": "https://example.com",
"policy_uri": "https://example.com/privacy",
"tos_uri": "https://example.com/terms"
}
```
## Server Metadata
MCPHub provides OAuth 2.0 Authorization Server Metadata (RFC 8414) at:
```
GET /.well-known/oauth-authorization-server
```
Response (with dynamic registration enabled):
```json
{
"issuer": "http://localhost:3000",
"authorization_endpoint": "http://localhost:3000/oauth/authorize",
"token_endpoint": "http://localhost:3000/oauth/token",
"userinfo_endpoint": "http://localhost:3000/oauth/userinfo",
"registration_endpoint": "http://localhost:3000/oauth/register",
"scopes_supported": ["read", "write"],
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"token_endpoint_auth_methods_supported": ["none", "client_secret_basic", "client_secret_post"],
"code_challenge_methods_supported": ["S256", "plain"]
}
```
## User Info Endpoint
Get authenticated user information (OpenID Connect compatible):
```bash
curl http://localhost:3000/oauth/userinfo \
-H "Authorization: Bearer ACCESS_TOKEN"
```
Response:
```json
{
"sub": "username",
"username": "username"
}
```
## Integration with ChatGPT Web
To integrate MCPHub with ChatGPT Web:
1. Enable OAuth server in MCPHub configuration
2. Create an OAuth client with ChatGPT's redirect URI
3. Configure ChatGPT Web MCP Connector:
- **MCP Server URL**: `http://your-mcphub-url/mcp`
- **Authentication**: OAuth
- **OAuth Client ID**: Your client ID
- **OAuth Client Secret**: Leave empty (PKCE flow)
- **Authorization URL**: `http://your-mcphub-url/oauth/authorize`
- **Token URL**: `http://your-mcphub-url/oauth/token`
- **Scopes**: `read write`
## Security Considerations
1. **HTTPS in Production**: Always use HTTPS in production to protect tokens in transit
2. **Secure Client Secrets**: If using confidential clients, store client secrets securely
3. **Token Storage**: Access tokens are stored in memory by default. For production, consider using a database
4. **Token Rotation**: Implement token rotation by using refresh tokens
5. **Scope Limitation**: Grant only necessary scopes to clients
6. **Redirect URI Validation**: Always validate redirect URIs strictly
7. **State Parameter**: Always use the state parameter to prevent CSRF attacks
8. **PKCE**: Use PKCE for public clients (strongly recommended)
9. **Rate Limiting**: For production deployments, implement rate limiting on OAuth endpoints to prevent brute force attacks. Consider using middleware like `express-rate-limit`
10. **Input Validation**: All OAuth parameters are validated, but additional application-level validation may be beneficial
11. **XSS Protection**: The authorization page escapes all user input to prevent XSS attacks
## Troubleshooting
### "OAuth server not available"
Make sure `oauthServer.enabled` is set to `true` in your configuration and restart MCPHub.
### "Invalid redirect_uri"
Ensure the redirect URI in the authorization request exactly matches one of the registered redirect URIs for the client.
### "Invalid client"
Verify the client ID is correct and the OAuth client exists in the configuration.
### Token expired
Use the refresh token to obtain a new access token, or re-authorize the application.
## Example: JavaScript Client
```javascript
// Generate PKCE parameters
const codeVerifier = crypto.randomBytes(32).toString('base64url');
const codeChallenge = crypto
.createHash('sha256')
.update(codeVerifier)
.digest('base64url');
// Store code verifier for later use
sessionStorage.setItem('codeVerifier', codeVerifier);
// Redirect to authorization endpoint
const authUrl = new URL('http://localhost:3000/oauth/authorize');
authUrl.searchParams.set('client_id', 'my-client-id');
authUrl.searchParams.set('redirect_uri', 'http://localhost:8080/callback');
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('scope', 'read write');
authUrl.searchParams.set('state', crypto.randomBytes(16).toString('hex'));
authUrl.searchParams.set('code_challenge', codeChallenge);
authUrl.searchParams.set('code_challenge_method', 'S256');
window.location.href = authUrl.toString();
// In callback handler:
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
const codeVerifier = sessionStorage.getItem('codeVerifier');
// Exchange code for token
const tokenResponse = await fetch('http://localhost:3000/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code,
redirect_uri: 'http://localhost:8080/callback',
client_id: 'my-client-id',
code_verifier: codeVerifier,
}),
});
const tokens = await tokenResponse.json();
// Store tokens securely
localStorage.setItem('accessToken', tokens.access_token);
localStorage.setItem('refreshToken', tokens.refresh_token);
// Use access token
const response = await fetch('http://localhost:3000/api/servers', {
headers: { Authorization: `Bearer ${tokens.access_token}` },
});
```
## References
- [OAuth 2.0 - RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749)
- [OAuth 2.0 Authorization Server Metadata - RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414)
- [PKCE - RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636)
- [OAuth 2.0 for Browser-Based Apps](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps)

View File

@@ -0,0 +1,209 @@
# OpenAPI Schema Support in MCPHub
MCPHub now supports both OpenAPI specification URLs and complete JSON schemas for OpenAPI server configuration. This allows you to either reference an external OpenAPI specification file or embed the complete schema directly in your configuration.
## Configuration Options
### 1. Using OpenAPI Specification URL (Traditional)
```json
{
"type": "openapi",
"openapi": {
"url": "https://api.example.com/openapi.json",
"version": "3.1.0",
"security": {
"type": "apiKey",
"apiKey": {
"name": "X-API-Key",
"in": "header",
"value": "your-api-key"
}
}
}
}
```
### 2. Using Complete JSON Schema (New)
```json
{
"type": "openapi",
"openapi": {
"schema": {
"openapi": "3.1.0",
"info": {
"title": "My API",
"version": "1.0.0"
},
"servers": [
{
"url": "https://api.example.com"
}
],
"paths": {
"/users": {
"get": {
"operationId": "getUsers",
"summary": "Get all users",
"responses": {
"200": {
"description": "List of users"
}
}
}
}
}
},
"version": "3.1.0",
"security": {
"type": "apiKey",
"apiKey": {
"name": "X-API-Key",
"in": "header",
"value": "your-api-key"
}
}
}
}
```
## Benefits of JSON Schema Support
1. **Offline Development**: No need for external URLs during development
2. **Version Control**: Schema changes can be tracked in your configuration
3. **Security**: No external dependencies or network calls required
4. **Customization**: Full control over the API specification
5. **Testing**: Easy to create test configurations with mock schemas
## Frontend Form Support
The web interface now includes:
- **Input Mode Selection**: Choose between "Specification URL" or "JSON Schema"
- **URL Input**: Traditional URL input field for external specifications
- **Schema Editor**: Large text area with syntax highlighting for JSON schema input
- **Validation**: Client-side JSON validation before submission
- **Help Text**: Contextual help for schema format
## API Validation
The backend validates that:
- At least one of `url` or `schema` is provided for OpenAPI servers
- JSON schemas are properly formatted when provided
- Security configurations are valid for both input modes
- All required OpenAPI fields are present
## Migration Guide
### From URL to Schema
If you want to convert an existing URL-based configuration to schema-based:
1. Download your OpenAPI specification from the URL
2. Copy the JSON content
3. Update your configuration to use the `schema` field instead of `url`
4. Paste the JSON content as the value of the `schema` field
### Maintaining Both
You can include both `url` and `schema` in your configuration. The system will prioritize the `schema` field if both are present.
## Examples
See the `examples/openapi-schema-config.json` file for complete configuration examples showing both URL and schema-based configurations.
## Technical Implementation
- **Backend**: OpenAPI client supports both SwaggerParser.dereference() with URLs and direct schema objects
- **Frontend**: Dynamic form rendering based on selected input mode
- **Validation**: Enhanced validation logic in server controllers
- **Type Safety**: Updated TypeScript interfaces for both input modes
## Header Passthrough Support
MCPHub supports passing through specific headers from tool call requests to upstream OpenAPI endpoints. This is useful for authentication tokens, API keys, and other request-specific headers.
### Configuration
Add `passthroughHeaders` to your OpenAPI configuration:
```json
{
"type": "openapi",
"openapi": {
"url": "https://api.example.com/openapi.json",
"version": "3.1.0",
"passthroughHeaders": ["Authorization", "X-API-Key", "X-Custom-Header"],
"security": {
"type": "apiKey",
"apiKey": {
"name": "X-API-Key",
"in": "header",
"value": "your-api-key"
}
}
}
}
```
### How It Works
1. **Configuration**: List header names in the `passthroughHeaders` array
2. **Tool Calls**: When calling tools via HTTP API, include headers in the request
3. **Passthrough**: Only configured headers are forwarded to the upstream API
4. **Case Insensitive**: Header matching is case-insensitive for flexibility
### Example Usage
```bash
# Call an OpenAPI tool with passthrough headers
curl -X POST "http://localhost:3000/api/tools/myapi/createUser" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-token" \
-H "X-API-Key: your-api-key" \
-H "X-Custom-Header: custom-value" \
-d '{"name": "John Doe", "email": "john@example.com"}'
```
In this example:
- If `passthroughHeaders` includes `["Authorization", "X-API-Key"]`
- Only `Authorization` and `X-API-Key` headers will be forwarded
- `X-Custom-Header` will be ignored (not in passthrough list)
- `Content-Type` is handled by the OpenAPI operation definition
### Security Considerations
- **Whitelist Only**: Only explicitly configured headers are passed through
- **Sensitive Data**: Be careful with headers containing sensitive information
- **Validation**: Upstream APIs should validate all received headers
- **Logging**: Headers may appear in logs - consider this for sensitive data
## Security Considerations
When using JSON schemas:
- Ensure schemas are properly validated before use
- Be aware that large schemas increase configuration file size
- Consider using URL-based approach for frequently changing APIs
- Store sensitive information (like API keys) in environment variables, not in schemas
## Troubleshooting
### Common Issues
1. **Invalid JSON**: Ensure your schema is valid JSON format
2. **Missing Required Fields**: OpenAPI schemas must include `openapi`, `info`, and `paths` fields
3. **Schema Size**: Very large schemas may impact performance
4. **Server Configuration**: Ensure the `servers` field in your schema points to the correct endpoints
### Validation Errors
The system provides detailed error messages for:
- Malformed JSON in schema field
- Missing required OpenAPI fields
- Invalid security configurations
- Network issues with URL-based configurations

172
docs/openapi-support.md Normal file
View File

@@ -0,0 +1,172 @@
# OpenAPI Support in MCPHub
MCPHub now supports OpenAPI 3.1.1 servers as a new server type, allowing you to integrate REST APIs directly into your MCP workflow.
## Features
-**Full OpenAPI 3.1.1 Support**: Load and parse OpenAPI specifications
-**Multiple Security Types**: None, API Key, HTTP Authentication, OAuth 2.0, OpenID Connect
-**Dynamic Tool Generation**: Automatically creates MCP tools from OpenAPI operations
-**Type Safety**: Full TypeScript support with proper type definitions
-**Frontend Integration**: Easy-to-use forms for configuring OpenAPI servers
-**Internationalization**: Support for English and Chinese languages
## Configuration
### Basic Configuration
```json
{
"type": "openapi",
"openapi": {
"url": "https://api.example.com/v1/openapi.json",
"version": "3.1.0",
"security": {
"type": "none"
}
}
}
```
### With API Key Authentication
```json
{
"type": "openapi",
"openapi": {
"url": "https://api.example.com/v1/openapi.json",
"version": "3.1.0",
"security": {
"type": "apiKey",
"apiKey": {
"name": "X-API-Key",
"in": "header",
"value": "your-api-key-here"
}
}
},
"headers": {
"Accept": "application/json"
}
}
```
### With HTTP Bearer Authentication
```json
{
"type": "openapi",
"openapi": {
"url": "https://api.example.com/v1/openapi.json",
"version": "3.1.0",
"security": {
"type": "http",
"http": {
"scheme": "bearer",
"credentials": "your-bearer-token-here"
}
}
}
}
```
## Supported Security Types
1. **None**: No authentication required
2. **API Key**: API key in header or query parameter
3. **HTTP**: Basic, Bearer, or Digest authentication
4. **OAuth 2.0**: OAuth 2.0 access tokens
5. **OpenID Connect**: OpenID Connect ID tokens
## How It Works
1. **Specification Loading**: The OpenAPI client fetches and parses the OpenAPI specification
2. **Tool Generation**: Each operation in the spec becomes an MCP tool
3. **Request Handling**: Tools handle parameter validation and API calls
4. **Response Processing**: API responses are returned as tool results
## Frontend Usage
1. Navigate to the Servers page
2. Click "Add Server"
3. Select "OpenAPI" as the server type
4. Enter the OpenAPI specification URL
5. Configure security settings if needed
6. Add any additional headers
7. Save the configuration
## Testing
You can test the OpenAPI integration using the provided test scripts:
```bash
# Test OpenAPI client directly
npx tsx test-openapi.ts
# Test full integration
npx tsx test-integration.ts
```
## Example: Swagger Petstore
The Swagger Petstore API is a perfect example for testing:
```json
{
"type": "openapi",
"openapi": {
"url": "https://petstore3.swagger.io/api/v3/openapi.json",
"version": "3.1.0",
"security": {
"type": "none"
}
}
}
```
This will create tools like:
- `addPet`: Add a new pet to the store
- `findPetsByStatus`: Find pets by status
- `getPetById`: Find pet by ID
- And many more...
## Error Handling
The OpenAPI client includes comprehensive error handling:
- Network errors are properly caught and reported
- Invalid specifications are rejected with clear error messages
- API errors include response status and body information
- Type validation ensures proper parameter handling
## Limitations
- Only supports OpenAPI 3.x specifications (3.0.0 and above)
- Complex authentication flows (like OAuth 2.0 authorization code flow) require manual token management
- Large specifications may take time to parse initially
- Some advanced OpenAPI features may not be fully supported
## Contributing
To add new features or fix bugs in the OpenAPI integration:
1. Backend types: `src/types/index.ts`
2. OpenAPI client: `src/clients/openapi.ts`
3. Service integration: `src/services/mcpService.ts`
4. Frontend forms: `frontend/src/components/ServerForm.tsx`
5. Internationalization: `frontend/src/locales/`
## Troubleshooting
**Q: My OpenAPI server won't connect**
A: Check that the specification URL is accessible and returns valid JSON/YAML
**Q: Tools aren't showing up**
A: Verify that your OpenAPI specification includes valid operations with required fields
**Q: Authentication isn't working**
A: Double-check your security configuration matches the API's requirements
**Q: Getting CORS errors**
A: The API server needs to allow CORS requests from your MCPHub domain

226
docs/quickstart.mdx Normal file
View File

@@ -0,0 +1,226 @@
---
title: 'Quick Start Guide'
description: 'Get MCPHub running in 5 minutes'
---
## Installation
<Tabs>
<Tab title="Docker (Recommended)">
The fastest way to get started with MCPHub is using Docker:
```bash
# Run with default configuration
docker run -p 3000:3000 samanhappy/mcphub
```
Or mount your custom configuration:
```bash
# Run with custom MCP settings
docker run -p 3000:3000 \
-v $(pwd)/mcp_settings.json:/app/mcp_settings.json \
samanhappy/mcphub
```
</Tab>
<Tab title="Local Development">
For development or customization:
```bash
# Clone the repository
git clone https://github.com/samanhappy/mcphub.git
cd mcphub
# Install dependencies
pnpm install
# Start development servers
pnpm dev
```
This starts both backend (port 3001) and frontend (port 5173) in development mode.
</Tab>
<Tab title="npm Package">
Install MCPHub as a global package:
```bash
# Install globally
npm install -g @samanhappy/mcphub
# Run MCPHub
mcphub
```
</Tab>
</Tabs>
## Initial Setup
### 1. Access the Dashboard
Open your browser and navigate to:
```
http://localhost:3000
```
### 2. Login
Use the default credentials:
- **Username**: `admin`
- **Password**: `admin123`
<Warning>Change these default credentials immediately after first login for security.</Warning>
### 3. Configure Your First MCP Server
1. Click **"Add Server"** in the dashboard
2. Enter server details:
- **Name**: A unique identifier (e.g., `fetch`)
- **Command**: The executable command (`uvx`)
- **Args**: Command arguments (`["mcp-server-fetch"]`)
- **Environment**: Any required environment variables
Example configuration for a fetch server:
```json
{
"name": "fetch",
"command": "uvx",
"args": ["mcp-server-fetch"],
"env": {}
}
```
## Basic Usage
### Connecting AI Clients
Once your servers are configured, connect your AI clients using MCPHub endpoints:
<Tabs>
<Tab title="All Servers">
Access all configured MCP servers: ``` http://localhost:3000/mcp ```
</Tab>
<Tab title="Specific Group">
Access servers in a specific group: ``` http://localhost:3000/mcp/{groupName} ```
</Tab>
<Tab title="Individual Server">
Access a single server: ``` http://localhost:3000/mcp/{serverName} ```
</Tab>
<Tab title="Smart Routing">
Use AI-powered tool discovery: ``` http://localhost:3000/mcp/$smart ```
<Info>Smart routing requires PostgreSQL with pgvector and an OpenAI API key.</Info>
</Tab>
</Tabs>
### Example: Adding Popular MCP Servers
Here are some popular MCP servers you can add:
<AccordionGroup>
<Accordion title="Web Fetch Server">
```json
{
"name": "fetch",
"command": "uvx",
"args": ["mcp-server-fetch"]
}
```
</Accordion>
<Accordion title="Playwright Browser Automation">
```json
{
"name": "playwright",
"command": "npx",
"args": ["@playwright/mcp@latest", "--headless"]
}
```
</Accordion>
<Accordion title="Amap Maps (with API key)">
```json
{
"name": "amap",
"command": "npx",
"args": ["-y", "@amap/amap-maps-mcp-server"],
"env": {
"AMAP_MAPS_API_KEY": "your-api-key-here"
}
}
```
</Accordion>
<Accordion title="Slack Integration">
```json
{
"name": "slack",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-slack"],
"env": {
"SLACK_BOT_TOKEN": "your-bot-token",
"SLACK_TEAM_ID": "your-team-id"
}
}
```
</Accordion>
</AccordionGroup>
{/* ## Verification
Test your setup by making a simple request:
```bash
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}'
```
You should receive a list of available tools from your configured MCP servers. */}
## Next Steps
<CardGroup cols={2}>
<Card title="Server Management" icon="server" href="/features/server-management">
Learn advanced server configuration and management
</Card>
<Card title="Group Management" icon="users" href="/features/group-management">
Organize servers into logical groups
</Card>
<Card title="Smart Routing" icon="route" href="/features/smart-routing">
Set up AI-powered tool discovery
</Card>
<Card title="API Reference" icon="code" href="/api-reference/introduction">
Explore the complete API documentation
</Card>
</CardGroup>
## Troubleshooting
<AccordionGroup>
<Accordion title="Server won't start">
- Check if the MCP server command is accessible in your PATH - Verify environment variables are
correctly set - Check MCPHub logs for detailed error messages
</Accordion>
<Accordion title="Can't connect from AI client">
- Ensure MCPHub is running on the correct port - Check firewall settings - Verify the endpoint
URL format
</Accordion>
<Accordion title="Authentication issues">
- Verify credentials are correct - Check if JWT token is valid - Try clearing browser cache and
cookies
</Accordion>
</AccordionGroup>
Need more help? Join our [Discord community](https://discord.gg/qMKNsn5Q) for support!

View File

@@ -0,0 +1,4 @@
One of the core principles of software development is DRY (Don't Repeat
Yourself). This is a principle that apply to documentation as
well. If you find yourself repeating the same content in multiple places, you
should consider creating a custom snippet to keep your content in sync.

172
docs/testing-framework.md Normal file
View File

@@ -0,0 +1,172 @@
# 测试框架和自动化测试实现报告
## 概述
本项目已成功引入现代化的测试框架和自动化测试流程。实现了基于Jest的测试环境支持TypeScript、ES模块并包含完整的CI/CD配置。
## 已实现的功能
### 1. 测试框架配置
- **Jest配置**: 使用`jest.config.cjs`配置文件支持ES模块和TypeScript
- **覆盖率报告**: 配置了代码覆盖率收集和报告
- **测试环境**: 支持Node.js环境的单元测试和集成测试
- **模块映射**: 配置了路径别名支持
### 2. 测试工具和辅助函数
创建了完善的测试工具库 (`tests/utils/testHelpers.ts`):
- **认证工具**: JWT token生成和管理
- **HTTP测试**: Supertest集成用于API测试
- **数据生成**: 测试数据工厂函数
- **响应断言**: 自定义API响应验证器
- **环境管理**: 测试环境变量配置
### 3. 测试用例实现
已实现的测试场景:
#### 基础配置测试 (`tests/basic.test.ts`)
- Jest配置验证
- 异步操作支持测试
- 自定义匹配器验证
#### 认证逻辑测试 (`tests/auth.logic.test.ts`)
- 用户登录逻辑
- 密码验证
- JWT生成和验证
- 错误处理场景
- 用户数据验证
#### 路径工具测试 (`tests/utils/pathLogic.test.ts`)
- 配置文件路径解析
- 环境变量处理
- 文件系统操作
- 错误处理和边界条件
- 跨平台路径处理
### 4. CI/CD配置
GitHub Actions配置 (`.github/workflows/ci.yml`):
- **多Node.js版本支持**: 18.x和20.x
- **自动化测试流程**:
- 代码检查 (ESLint)
- 类型检查 (TypeScript)
- 单元测试执行
- 覆盖率报告
- **构建验证**: 应用构建和产物验证
- **集成测试**: 包含数据库环境的集成测试
### 5. 测试脚本
`package.json`中添加的测试命令:
```json
{
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"test:verbose": "jest --verbose",
"test:ci": "jest --ci --coverage --watchAll=false"
}
```
## 测试结果
当前测试统计:
- **测试套件**: 3个
- **测试用例**: 19个
- **通过率**: 100%
- **执行时间**: ~15秒
### 测试覆盖的功能模块
1. **认证系统**: 用户登录、JWT处理、密码验证
2. **配置管理**: 文件路径解析、环境变量处理
3. **基础设施**: Jest配置、测试工具验证
## 技术特点
### 现代化特性
- **ES模块支持**: 完全支持ES2022模块语法
- **TypeScript集成**: 类型安全的测试编写
- **异步测试**: Promise和async/await支持
- **模拟系统**: Jest mock功能的深度使用
- **参数化测试**: 数据驱动的测试用例
### 最佳实践
- **测试隔离**: 每个测试用例独立运行
- **Mock管理**: 统一的mock清理和重置
- **错误处理**: 完整的错误场景测试
- **边界测试**: 输入验证和边界条件覆盖
- **文档化**: 清晰的测试用例命名和描述
## 后续扩展计划
### 短期目标
1. **API测试**: 为REST API端点添加集成测试
2. **数据库测试**: 添加数据模型和存储层测试
3. **中间件测试**: 认证和权限中间件测试
4. **服务层测试**: 核心业务逻辑测试
### 中期目标
1. **端到端测试**: 使用Playwright或Cypress
2. **性能测试**: API响应时间和负载测试
3. **安全测试**: 输入验证和安全漏洞测试
4. **契约测试**: API契约验证
### 长期目标
1. **测试数据管理**: 测试数据库和fixture管理
2. **视觉回归测试**: UI组件的视觉测试
3. **监控集成**: 生产环境测试监控
4. **自动化测试报告**: 详细的测试报告和趋势分析
## 开发指南
### 添加新测试用例
1.`tests/`目录下创建对应的测试文件
2. 使用`testHelpers.ts`中的工具函数
3. 遵循命名约定: `*.test.ts``*.spec.ts`
4. 确保测试用例具有清晰的描述和断言
### 运行测试
```bash
# 运行所有测试
pnpm test
# 监听模式
pnpm test:watch
# 生成覆盖率报告
pnpm test:coverage
# CI模式运行
pnpm test:ci
```
### Mock最佳实践
-`beforeEach`中清理所有mock
- 使用具体的mock实现而不是空函数
- 验证mock被正确调用
- 保持mock的一致性和可维护性
## 结论
本项目已成功建立了完整的现代化测试框架,具备以下优势:
1. **高度可扩展**: 易于添加新的测试用例和测试类型
2. **开发友好**: 丰富的工具函数和清晰的结构
3. **CI/CD就绪**: 完整的自动化流水线配置
4. **质量保证**: 代码覆盖率和持续测试验证
这个测试框架为项目的持续发展和质量保证提供了坚实的基础,支持敏捷开发和持续集成的最佳实践。

View File

@@ -0,0 +1,147 @@
---
title: "身份验证"
description: "管理用户和身份验证。"
---
import { Card, Cards } from 'mintlify';
<Card
title="POST /api/auth/login"
href="#login"
>
登录以获取 JWT 令牌。
</Card>
<Card
title="POST /api/auth/register"
href="#register"
>
注册一个新用户。
</Card>
<Card
title="GET /api/auth/user"
href="#get-current-user"
>
获取当前已验证的用户。
</Card>
<Card
title="POST /api/auth/change-password"
href="#change-password"
>
更改当前用户的密码。
</Card>
---
### 登录
验证用户身份并返回 JWT 令牌及用户详细信息。
- **端点**: `/api/auth/login`
- **方法**: `POST`
- **正文**:
- `username` (string, 必填): 用户名。
- `password` (string, 必填): 用户密码。
- **请求示例**:
```json
{
"username": "admin",
"password": "admin123"
}
```
- **成功响应**:
```json
{
"success": true,
"message": "登录成功",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"username": "admin",
"isAdmin": true,
"permissions": { ... }
}
}
```
---
### 注册
注册一个新用户并返回 JWT 令牌。
- **端点**: `/api/auth/register`
- **方法**: `POST`
- **正文**:
- `username` (string, 必填): 新的用户名。
- `password` (string, 必填): 新的用户密码 (至少6个字符)。
- `isAdmin` (boolean, 可选): 用户是否应有管理员权限。
- **请求示例**:
```json
{
"username": "newuser",
"password": "password123",
"isAdmin": false
}
```
- **成功响应**:
```json
{
"success": true,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"username": "newuser",
"isAdmin": false,
"permissions": { ... }
}
}
```
---
### 获取当前用户
检索当前通过身份验证的用户的个人资料。
- **端点**: `/api/auth/user`
- **方法**: `GET`
- **身份验证**: 需要承载令牌 (Bearer Token)。
- **成功响应**:
```json
{
"success": true,
"user": {
"username": "admin",
"isAdmin": true,
"permissions": { ... }
}
}
```
---
### 更改密码
允许通过身份验证的用户更改其密码。
- **端点**: `/api/auth/change-password`
- **方法**: `POST`
- **身份验证**: 需要承载令牌 (Bearer Token)。
- **正文**:
- `currentPassword` (string, 必填): 用户的当前密码。
- `newPassword` (string, 必填): 新的密码 (至少6个字符)。
- **请求示例**:
```json
{
"currentPassword": "oldpassword",
"newPassword": "newpassword123"
}
```
- **成功响应**:
```json
{
"success": true,
"message": "密码更新成功"
}
```

View File

@@ -0,0 +1,111 @@
---
title: "配置"
description: "管理和检索系统级配置。"
---
import { Card, Cards } from 'mintlify';
<Card title="PUT /api/system-config" href="#update-system-config">更新主系统配置。</Card>
<Card title="GET /api/settings" href="#get-all-settings">获取所有系统设置,包括服务器和群组。</Card>
<Card title="GET /config" href="#get-runtime-config">获取前端的公共运行时配置。</Card>
<Card title="GET /public-config" href="#get-public-config">获取公共配置以检查是否跳过身份验证。</Card>
---
### 更新系统配置
更新系统配置的各个部分。您只需提供要更新部分的键。
- **端点**: `/api/system-config`
- **方法**: `PUT`
- **正文**: 一个 JSON 对象,包含以下一个或多个顶级键:`routing`、`install`、`smartRouting`、`mcpRouter`。
#### 路由配置 (`routing`)
- `enableGlobalRoute` (boolean): 启用或禁用全局 `/api/mcp` 路由。
- `enableGroupNameRoute` (boolean): 启用或禁用基于群组的路由 (例如 `/api/mcp/group/:groupName`)。
- `enableBearerAuth` (boolean): 为 MCP 路由启用承载令牌身份验证。
- `bearerAuthKey` (string): 用于承载身份验证的密钥。
- `skipAuth` (boolean): 如果为 true则跳过所有身份验证使实例公开。
#### 安装配置 (`install`)
- `pythonIndexUrl` (string): 用于安装的 Python 包索引 (PyPI) 的基础 URL。
- `npmRegistry` (string): 用于安装的 npm 注册表 URL。
- `baseUrl` (string): 此 MCPHub 实例的公共基础 URL。
#### 智能路由配置 (`smartRouting`)
- `enabled` (boolean): 启用或禁用智能路由功能。
- `dbUrl` (string): 用于存储嵌入的数据库连接 URL。
- `openaiApiBaseUrl` (string): 用于生成嵌入的 OpenAI 兼容 API 的基础 URL。
- `openaiApiKey` (string): 嵌入服务的 API 密钥。
- `openaiApiEmbeddingModel` (string): 要使用的嵌入模型的名称。
#### MCP 路由器配置 (`mcpRouter`)
- `apiKey` (string): MCP 路由器服务的 API 密钥。
- `referer` (string): 用于 MCP 路由器请求的 referer 头。
- `title` (string): 在 MCP 路由器上显示的此实例的标题。
- `baseUrl` (string): MCP 路由器 API 的基础 URL。
- **请求示例**:
```json
{
"routing": {
"skipAuth": true
},
"smartRouting": {
"enabled": true,
"dbUrl": "postgresql://user:pass@host:port/db"
}
}
```
---
### 获取所有设置
检索实例的整个设置对象,包括所有服务器配置、群组和系统设置。这是 `mcp_settings.json` 文件的完整转储。
- **端点**: `/api/settings`
- **方法**: `GET`
---
### 获取运行时配置
检索前端应用程序所需的基本运行时配置。此端点不需要身份验证。
- **端点**: `/config`
- **方法**: `GET`
- **成功响应**:
```json
{
"success": true,
"data": {
"basePath": "",
"version": "1.0.0",
"name": "MCPHub"
}
}
```
---
### 获取公共配置
检索公共配置,主要用于检查是否跳过身份验证。这允许前端在用户登录前相应地调整其行为。此端点不需要身份验证。
- **端点**: `/public-config`
- **方法**: `GET`
- **成功响应**:
```json
{
"success": true,
"data": {
"skipAuth": false,
"permissions": {}
}
}
```

View File

@@ -0,0 +1,212 @@
---
title: "群组"
description: "管理服务器群组以组织和路由请求。"
---
import { Card, Cards } from 'mintlify';
<Card title="GET /api/groups" href="#get-all-groups">获取所有群组的列表。</Card>
<Card title="POST /api/groups" href="#create-a-new-group">创建一个新群组。</Card>
<Card title="GET /api/groups/:id" href="#get-a-group">获取特定群组的详细信息。</Card>
<Card title="PUT /api/groups/:id" href="#update-a-group">更新现有群组。</Card>
<Card title="DELETE /api/groups/:id" href="#delete-a-group">删除一个群组。</Card>
<Card title="POST /api/groups/:id/servers" href="#add-server-to-group">将服务器添加到群组。</Card>
<Card title="DELETE /api/groups/:id/servers/:serverName" href="#remove-server-from-group">从群组中删除服务器。</Card>
<Card title="PUT /api/groups/:id/servers/batch" href="#batch-update-group-servers">批量更新群组中的服务器。</Card>
<Card title="GET /api/groups/:id/server-configs" href="#get-group-server-configs">获取群组中详细的服务器配置。</Card>
<Card title="PUT /api/groups/:id/server-configs/:serverName/tools" href="#update-group-server-tools">更新群组中服务器的工具选择。</Card>
---
### 获取所有群组
检索所有服务器群组的列表。
- **端点**: `/api/groups`
- **方法**: `GET`
- **成功响应**:
```json
{
"success": true,
"data": [
{
"id": "group-1",
"name": "我的群组",
"description": "服务器的集合。",
"servers": ["server1", "server2"],
"owner": "admin"
}
]
}
```
---
### 创建一个新群组
创建一个新的服务器群组。
- **端点**: `/api/groups`
- **方法**: `POST`
- **正文**:
- `name` (string, 必填): 群组的名称。
- `description` (string, 可选): 群组的描述。
- `servers` (array of strings, 可选): 要包含在群组中的服务器名称列表。
- **请求示例**:
```json
{
"name": "我的新群组",
"description": "新群组的描述",
"servers": ["server1", "server2"]
}
```
---
### 获取一个群组
通过 ID 或名称检索特定群组的详细信息。
- **端点**: `/api/groups/:id`
- **方法**: `GET`
- **参数**:
- `:id` (string, 必填): 群组的 ID 或名称。
---
### 更新一个群组
更新现有群组的名称、描述或服务器列表。
- **端点**: `/api/groups/:id`
- **方法**: `PUT`
- **参数**:
- `:id` (string, 必填): 要更新的群组的 ID 或名称。
- **正文**:
- `name` (string, 可选): 群组的新名称。
- `description` (string, 可选): 群组的新描述。
- `servers` (array, 可选): 群组的新服务器列表。格式请参阅 [批量更新群组服务器](#batch-update-group-servers)。
- **请求示例**:
```json
{
"name": "更新后的群组名称",
"description": "更新后的描述"
}
```
---
### 删除一个群组
通过 ID 或名称删除一个群组。
- **端点**: `/api/groups/:id`
- **方法**: `DELETE`
- **参数**:
- `:id` (string, 必填): 要删除的群组的 ID 或名称。
---
### 将服务器添加到群组
将单个服务器添加到群组。
- **端点**: `/api/groups/:id/servers`
- **方法**: `POST`
- **参数**:
- `:id` (string, 必填): 群组的 ID 或名称。
- **正文**:
- `serverName` (string, 必填): 要添加的服务器的名称。
- **请求示例**:
```json
{
"serverName": "my-server"
}
```
---
### 从群组中删除服务器
从群组中删除单个服务器。
- **端点**: `/api/groups/:id/servers/:serverName`
- **方法**: `DELETE`
- **参数**:
- `:id` (string, 必填): 群组的 ID 或名称。
- `:serverName` (string, 必填): 要删除的服务器的名称。
---
### 批量更新群组服务器
用新的列表替换群组中的所有服务器。该列表可以是简单的字符串或详细的配置对象。
- **端点**: `/api/groups/:id/servers/batch`
- **方法**: `PUT`
- **参数**:
- `:id` (string, 必填): 群组的 ID 或名称。
- **正文**:
- `servers` (array, 必填): 服务器名称(字符串)或服务器配置对象的数组。
- **请求示例 (简单)**:
```json
{
"servers": ["server1", "server2"]
}
```
- **请求示例 (详细)**:
```json
{
"servers": [
{ "name": "server1", "tools": "all" },
{ "name": "server2", "tools": ["toolA", "toolB"] }
]
}
```
---
### 获取群组服务器配置
检索群组内所有服务器的详细配置,包括启用了哪些工具。
- **端点**: `/api/groups/:id/server-configs`
- **方法**: `GET`
- **参数**:
- `:id` (string, 必填): 群组的 ID 或名称。
- **成功响应**:
```json
{
"success": true,
"data": [
{
"name": "server1",
"tools": "all"
},
{
"name": "server2",
"tools": ["toolA", "toolB"]
}
]
}
```
---
### 更新群组服务器工具
更新群组内特定服务器的工具选择。
- **端点**: `/api/groups/:id/server-configs/:serverName/tools`
- **方法**: `PUT`
- **参数**:
- `:id` (string, 必填): 群组的 ID 或名称。
- `:serverName` (string, 必填): 要更新的服务器的名称。
- **正文**:
- `tools` (string or array of strings, 必填): 字符串 `"all"` 表示启用所有工具,或一个工具名称数组以指定启用哪些工具。
- **请求示例**:
```json
{
"tools": ["toolA", "toolC"]
}
```

View File

@@ -0,0 +1,13 @@
---
title: "介绍"
description: "欢迎来到 MCPHub API 文档。"
---
MCPHub API 提供了一整套端点来管理您的 MCP 服务器、群组、用户等。该 API 分为两个主要类别:
- **MCP 端点**: 这些是与您的 MCP 服务器交互的主要端点。它们提供了一个统一的界面,用于向您的服务器发送请求并实时接收响应。
- **管理 API**: 这些端点用于管理 MCPHub 实例本身。这包括管理服务器、群组、用户和系统设置。
所有 API 端点都在 `/api` 路径下可用。例如,获取所有服务器的端点是 `/api/servers`。
大多数管理 API 端点都需要身份验证。有关更多详细信息,请参阅[身份验证](/api-reference/auth)部分。

View File

@@ -0,0 +1,81 @@
---
title: "日志"
description: "访问和管理服务器日志。"
---
import { Card, Cards } from 'mintlify';
<Card
title="GET /api/logs"
href="#get-all-logs"
>
获取所有日志。
</Card>
<Card
title="DELETE /api/logs"
href="#clear-logs"
>
清除所有日志。
</Card>
<Card
title="GET /api/logs/stream"
href="#stream-logs"
>
实时流式传输日志。
</Card>
---
### 获取所有日志
检索所有存储的日志。
- **端点**: `/api/logs`
- **方法**: `GET`
- **成功响应**:
```json
{
"success": true,
"data": [
{
"timestamp": "2023-10-27T10:00:00.000Z",
"level": "info",
"message": "服务器成功启动。",
"service": "system"
}
]
}
```
---
### 清除日志
删除所有存储的日志。
- **端点**: `/api/logs`
- **方法**: `DELETE`
- **成功响应**:
```json
{
"success": true,
"message": "日志清除成功"
}
```
---
### 流式传输日志
使用服务器发送事件 (SSE) 实时流式传输日志。连接将保持打开状态,新的日志条目将在发生时发送。
- **端点**: `/api/logs/stream`
- **方法**: `GET`
- **响应格式**: 该流发送带有包含 JSON 对象的 `data` 字段的事件。第一个事件的 `type` 为 `initial`,包含所有历史日志。后续事件的 `type` 为 `log`,包含单个新日志条目。
- **事件示例**:
```
data: {"type":"log","log":{"timestamp":"2023-10-27T10:00:05.000Z","level":"debug","message":"正在处理 /api/some-endpoint 的请求","service":"mcp-server"}}
```

Some files were not shown because too many files have changed in this diff Show More