@samanhappy/mcphub 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/package.json +8 -5
  2. package/.env.example +0 -2
  3. package/.eslintrc.json +0 -25
  4. package/.github/workflows/build.yml +0 -51
  5. package/.github/workflows/release.yml +0 -19
  6. package/.prettierrc +0 -7
  7. package/Dockerfile +0 -51
  8. package/assets/amap-edit.png +0 -0
  9. package/assets/amap-result.png +0 -0
  10. package/assets/cherry-mcp.png +0 -0
  11. package/assets/cursor-mcp.png +0 -0
  12. package/assets/cursor-query.png +0 -0
  13. package/assets/cursor-tools.png +0 -0
  14. package/assets/dashboard.png +0 -0
  15. package/assets/dashboard.zh.png +0 -0
  16. package/assets/group.png +0 -0
  17. package/assets/group.zh.png +0 -0
  18. package/assets/market.zh.png +0 -0
  19. package/assets/wegroup.jpg +0 -0
  20. package/assets/wegroup.png +0 -0
  21. package/assets/wexin.png +0 -0
  22. package/bin/mcphub.js +0 -3
  23. package/doc/intro.md +0 -73
  24. package/doc/intro2.md +0 -232
  25. package/entrypoint.sh +0 -10
  26. package/frontend/favicon.ico +0 -0
  27. package/frontend/index.html +0 -13
  28. package/frontend/postcss.config.js +0 -6
  29. package/frontend/src/App.tsx +0 -44
  30. package/frontend/src/components/AddGroupForm.tsx +0 -132
  31. package/frontend/src/components/AddServerForm.tsx +0 -90
  32. package/frontend/src/components/ChangePasswordForm.tsx +0 -158
  33. package/frontend/src/components/EditGroupForm.tsx +0 -149
  34. package/frontend/src/components/EditServerForm.tsx +0 -76
  35. package/frontend/src/components/GroupCard.tsx +0 -143
  36. package/frontend/src/components/MarketServerCard.tsx +0 -153
  37. package/frontend/src/components/MarketServerDetail.tsx +0 -297
  38. package/frontend/src/components/ProtectedRoute.tsx +0 -27
  39. package/frontend/src/components/ServerCard.tsx +0 -230
  40. package/frontend/src/components/ServerForm.tsx +0 -276
  41. package/frontend/src/components/icons/LucideIcons.tsx +0 -14
  42. package/frontend/src/components/layout/Content.tsx +0 -17
  43. package/frontend/src/components/layout/Header.tsx +0 -61
  44. package/frontend/src/components/layout/Sidebar.tsx +0 -98
  45. package/frontend/src/components/ui/Badge.tsx +0 -33
  46. package/frontend/src/components/ui/Button.tsx +0 -0
  47. package/frontend/src/components/ui/DeleteDialog.tsx +0 -48
  48. package/frontend/src/components/ui/Pagination.tsx +0 -128
  49. package/frontend/src/components/ui/Toast.tsx +0 -96
  50. package/frontend/src/components/ui/ToggleGroup.tsx +0 -134
  51. package/frontend/src/components/ui/ToolCard.tsx +0 -38
  52. package/frontend/src/contexts/AuthContext.tsx +0 -159
  53. package/frontend/src/contexts/ToastContext.tsx +0 -60
  54. package/frontend/src/hooks/useGroupData.ts +0 -232
  55. package/frontend/src/hooks/useMarketData.ts +0 -410
  56. package/frontend/src/hooks/useServerData.ts +0 -306
  57. package/frontend/src/hooks/useSettingsData.ts +0 -131
  58. package/frontend/src/i18n.ts +0 -42
  59. package/frontend/src/index.css +0 -20
  60. package/frontend/src/layouts/MainLayout.tsx +0 -33
  61. package/frontend/src/locales/en.json +0 -214
  62. package/frontend/src/locales/zh.json +0 -214
  63. package/frontend/src/main.tsx +0 -12
  64. package/frontend/src/pages/Dashboard.tsx +0 -206
  65. package/frontend/src/pages/GroupsPage.tsx +0 -116
  66. package/frontend/src/pages/LoginPage.tsx +0 -104
  67. package/frontend/src/pages/MarketPage.tsx +0 -356
  68. package/frontend/src/pages/ServersPage.tsx +0 -144
  69. package/frontend/src/pages/SettingsPage.tsx +0 -149
  70. package/frontend/src/services/authService.ts +0 -141
  71. package/frontend/src/types/index.ts +0 -160
  72. package/frontend/src/utils/cn.ts +0 -10
  73. package/frontend/tsconfig.json +0 -31
  74. package/frontend/tsconfig.node.json +0 -10
  75. package/frontend/vite.config.ts +0 -26
  76. package/googled76ca578b6543fbc.html +0 -1
  77. package/jest.config.js +0 -10
  78. package/mcp_settings.json +0 -45
  79. package/servers.json +0 -74722
  80. package/src/config/index.ts +0 -46
  81. package/src/controllers/authController.ts +0 -179
  82. package/src/controllers/groupController.ts +0 -341
  83. package/src/controllers/marketController.ts +0 -154
  84. package/src/controllers/serverController.ts +0 -303
  85. package/src/index.ts +0 -17
  86. package/src/middlewares/auth.ts +0 -28
  87. package/src/middlewares/index.ts +0 -43
  88. package/src/models/User.ts +0 -103
  89. package/src/routes/index.ts +0 -96
  90. package/src/server.ts +0 -72
  91. package/src/services/groupService.ts +0 -232
  92. package/src/services/marketService.ts +0 -116
  93. package/src/services/mcpService.ts +0 -385
  94. package/src/services/sseService.ts +0 -119
  95. package/src/types/index.ts +0 -129
  96. package/src/utils/migration.ts +0 -52
  97. package/tsconfig.json +0 -17
@@ -1,159 +0,0 @@
1
- import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
2
- import { AuthState, IUser } from '../types';
3
- import * as authService from '../services/authService';
4
-
5
- // Initial auth state
6
- const initialState: AuthState = {
7
- token: null,
8
- isAuthenticated: false,
9
- loading: true,
10
- user: null,
11
- error: null,
12
- };
13
-
14
- // Create auth context
15
- const AuthContext = createContext<{
16
- auth: AuthState;
17
- login: (username: string, password: string) => Promise<boolean>;
18
- register: (username: string, password: string, isAdmin?: boolean) => Promise<boolean>;
19
- logout: () => void;
20
- }>({
21
- auth: initialState,
22
- login: async () => false,
23
- register: async () => false,
24
- logout: () => {},
25
- });
26
-
27
- // Auth provider component
28
- export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
29
- const [auth, setAuth] = useState<AuthState>(initialState);
30
-
31
- // Load user if token exists
32
- useEffect(() => {
33
- const loadUser = async () => {
34
- const token = authService.getToken();
35
-
36
- if (!token) {
37
- setAuth({
38
- ...initialState,
39
- loading: false,
40
- });
41
- return;
42
- }
43
-
44
- try {
45
- const response = await authService.getCurrentUser();
46
-
47
- if (response.success && response.user) {
48
- setAuth({
49
- token,
50
- isAuthenticated: true,
51
- loading: false,
52
- user: response.user,
53
- error: null,
54
- });
55
- } else {
56
- authService.removeToken();
57
- setAuth({
58
- ...initialState,
59
- loading: false,
60
- });
61
- }
62
- } catch (error) {
63
- authService.removeToken();
64
- setAuth({
65
- ...initialState,
66
- loading: false,
67
- });
68
- }
69
- };
70
-
71
- loadUser();
72
- }, []);
73
-
74
- // Login function
75
- const login = async (username: string, password: string): Promise<boolean> => {
76
- try {
77
- const response = await authService.login({ username, password });
78
-
79
- if (response.success && response.token && response.user) {
80
- setAuth({
81
- token: response.token,
82
- isAuthenticated: true,
83
- loading: false,
84
- user: response.user,
85
- error: null,
86
- });
87
- return true;
88
- } else {
89
- setAuth({
90
- ...initialState,
91
- loading: false,
92
- error: response.message || 'Authentication failed',
93
- });
94
- return false;
95
- }
96
- } catch (error) {
97
- setAuth({
98
- ...initialState,
99
- loading: false,
100
- error: 'Authentication failed',
101
- });
102
- return false;
103
- }
104
- };
105
-
106
- // Register function
107
- const register = async (
108
- username: string,
109
- password: string,
110
- isAdmin = false
111
- ): Promise<boolean> => {
112
- try {
113
- const response = await authService.register({ username, password, isAdmin });
114
-
115
- if (response.success && response.token && response.user) {
116
- setAuth({
117
- token: response.token,
118
- isAuthenticated: true,
119
- loading: false,
120
- user: response.user,
121
- error: null,
122
- });
123
- return true;
124
- } else {
125
- setAuth({
126
- ...initialState,
127
- loading: false,
128
- error: response.message || 'Registration failed',
129
- });
130
- return false;
131
- }
132
- } catch (error) {
133
- setAuth({
134
- ...initialState,
135
- loading: false,
136
- error: 'Registration failed',
137
- });
138
- return false;
139
- }
140
- };
141
-
142
- // Logout function
143
- const logout = (): void => {
144
- authService.logout();
145
- setAuth({
146
- ...initialState,
147
- loading: false,
148
- });
149
- };
150
-
151
- return (
152
- <AuthContext.Provider value={{ auth, login, register, logout }}>
153
- {children}
154
- </AuthContext.Provider>
155
- );
156
- };
157
-
158
- // Custom hook to use auth context
159
- export const useAuth = () => useContext(AuthContext);
@@ -1,60 +0,0 @@
1
- import React, { createContext, useContext, useState, ReactNode } from 'react';
2
- import Toast, { ToastType } from '@/components/ui/Toast';
3
-
4
- interface ToastContextProps {
5
- showToast: (message: string, type?: ToastType, duration?: number) => void;
6
- }
7
-
8
- const ToastContext = createContext<ToastContextProps | undefined>(undefined);
9
-
10
- export const useToast = () => {
11
- const context = useContext(ToastContext);
12
- if (!context) {
13
- throw new Error('useToast must be used within a ToastProvider');
14
- }
15
- return context;
16
- };
17
-
18
- interface ToastProviderProps {
19
- children: ReactNode;
20
- }
21
-
22
- export const ToastProvider: React.FC<ToastProviderProps> = ({ children }) => {
23
- const [toast, setToast] = useState<{
24
- message: string;
25
- type: ToastType;
26
- visible: boolean;
27
- duration: number;
28
- }>({
29
- message: '',
30
- type: 'info',
31
- visible: false,
32
- duration: 3000,
33
- });
34
-
35
- const showToast = (message: string, type: ToastType = 'info', duration: number = 3000) => {
36
- setToast({
37
- message,
38
- type,
39
- visible: true,
40
- duration,
41
- });
42
- };
43
-
44
- const hideToast = () => {
45
- setToast((prev) => ({ ...prev, visible: false }));
46
- };
47
-
48
- return (
49
- <ToastContext.Provider value={{ showToast }}>
50
- {children}
51
- <Toast
52
- message={toast.message}
53
- type={toast.type}
54
- duration={toast.duration}
55
- onClose={hideToast}
56
- visible={toast.visible}
57
- />
58
- </ToastContext.Provider>
59
- );
60
- };
@@ -1,232 +0,0 @@
1
- import { useState, useEffect, useCallback } from 'react';
2
- import { useTranslation } from 'react-i18next';
3
- import { Group, ApiResponse } from '@/types';
4
-
5
- export const useGroupData = () => {
6
- const { t } = useTranslation();
7
- const [groups, setGroups] = useState<Group[]>([]);
8
- const [loading, setLoading] = useState(true);
9
- const [error, setError] = useState<string | null>(null);
10
- const [refreshKey, setRefreshKey] = useState(0);
11
-
12
- const fetchGroups = useCallback(async () => {
13
- try {
14
- setLoading(true);
15
- const token = localStorage.getItem('mcphub_token');
16
- const response = await fetch('/api/groups', {
17
- headers: {
18
- 'x-auth-token': token || ''
19
- }
20
- });
21
-
22
- if (!response.ok) {
23
- throw new Error(`Status: ${response.status}`);
24
- }
25
-
26
- const data: ApiResponse<Group[]> = await response.json();
27
-
28
- if (data && data.success && Array.isArray(data.data)) {
29
- setGroups(data.data);
30
- } else {
31
- console.error('Invalid group data format:', data);
32
- setGroups([]);
33
- }
34
-
35
- setError(null);
36
- } catch (err) {
37
- console.error('Error fetching groups:', err);
38
- setError(err instanceof Error ? err.message : 'Failed to fetch groups');
39
- setGroups([]);
40
- } finally {
41
- setLoading(false);
42
- }
43
- }, []);
44
-
45
- // Trigger a refresh of the groups data
46
- const triggerRefresh = useCallback(() => {
47
- setRefreshKey(prev => prev + 1);
48
- }, []);
49
-
50
- // Create a new group with server associations
51
- const createGroup = async (name: string, description?: string, servers: string[] = []) => {
52
- try {
53
- const token = localStorage.getItem('mcphub_token');
54
- const response = await fetch('/api/groups', {
55
- method: 'POST',
56
- headers: {
57
- 'Content-Type': 'application/json',
58
- 'x-auth-token': token || ''
59
- },
60
- body: JSON.stringify({ name, description, servers }),
61
- });
62
-
63
- const result: ApiResponse<Group> = await response.json();
64
-
65
- if (!response.ok) {
66
- setError(result.message || t('groups.createError'));
67
- return null;
68
- }
69
-
70
- triggerRefresh();
71
- return result.data || null;
72
- } catch (err) {
73
- setError(err instanceof Error ? err.message : 'Failed to create group');
74
- return null;
75
- }
76
- };
77
-
78
- // Update an existing group with server associations
79
- const updateGroup = async (id: string, data: { name?: string; description?: string; servers?: string[] }) => {
80
- try {
81
- const token = localStorage.getItem('mcphub_token');
82
- const response = await fetch(`/api/groups/${id}`, {
83
- method: 'PUT',
84
- headers: {
85
- 'Content-Type': 'application/json',
86
- 'x-auth-token': token || ''
87
- },
88
- body: JSON.stringify(data),
89
- });
90
-
91
- const result: ApiResponse<Group> = await response.json();
92
-
93
- if (!response.ok) {
94
- setError(result.message || t('groups.updateError'));
95
- return null;
96
- }
97
-
98
- triggerRefresh();
99
- return result.data || null;
100
- } catch (err) {
101
- setError(err instanceof Error ? err.message : 'Failed to update group');
102
- return null;
103
- }
104
- };
105
-
106
- // Update servers in a group (for batch updates)
107
- const updateGroupServers = async (groupId: string, servers: string[]) => {
108
- try {
109
- const token = localStorage.getItem('mcphub_token');
110
- const response = await fetch(`/api/groups/${groupId}/servers/batch`, {
111
- method: 'PUT',
112
- headers: {
113
- 'Content-Type': 'application/json',
114
- 'x-auth-token': token || ''
115
- },
116
- body: JSON.stringify({ servers }),
117
- });
118
-
119
- const result: ApiResponse<Group> = await response.json();
120
-
121
- if (!response.ok) {
122
- setError(result.message || t('groups.updateError'));
123
- return null;
124
- }
125
-
126
- triggerRefresh();
127
- return result.data || null;
128
- } catch (err) {
129
- setError(err instanceof Error ? err.message : 'Failed to update group servers');
130
- return null;
131
- }
132
- };
133
-
134
- // Delete a group
135
- const deleteGroup = async (id: string) => {
136
- try {
137
- const token = localStorage.getItem('mcphub_token');
138
- const response = await fetch(`/api/groups/${id}`, {
139
- method: 'DELETE',
140
- headers: {
141
- 'x-auth-token': token || ''
142
- }
143
- });
144
-
145
- const result = await response.json();
146
-
147
- if (!response.ok) {
148
- setError(result.message || t('groups.deleteError'));
149
- return false;
150
- }
151
-
152
- triggerRefresh();
153
- return true;
154
- } catch (err) {
155
- setError(err instanceof Error ? err.message : 'Failed to delete group');
156
- return false;
157
- }
158
- };
159
-
160
- // Add server to a group
161
- const addServerToGroup = async (groupId: string, serverName: string) => {
162
- try {
163
- const token = localStorage.getItem('mcphub_token');
164
- const response = await fetch(`/api/groups/${groupId}/servers`, {
165
- method: 'POST',
166
- headers: {
167
- 'Content-Type': 'application/json',
168
- 'x-auth-token': token || ''
169
- },
170
- body: JSON.stringify({ serverName }),
171
- });
172
-
173
- const result: ApiResponse<Group> = await response.json();
174
-
175
- if (!response.ok) {
176
- setError(result.message || t('groups.serverAddError'));
177
- return null;
178
- }
179
-
180
- triggerRefresh();
181
- return result.data || null;
182
- } catch (err) {
183
- setError(err instanceof Error ? err.message : 'Failed to add server to group');
184
- return null;
185
- }
186
- };
187
-
188
- // Remove server from group
189
- const removeServerFromGroup = async (groupId: string, serverName: string) => {
190
- try {
191
- const token = localStorage.getItem('mcphub_token');
192
- const response = await fetch(`/api/groups/${groupId}/servers/${serverName}`, {
193
- method: 'DELETE',
194
- headers: {
195
- 'x-auth-token': token || ''
196
- }
197
- });
198
-
199
- const result: ApiResponse<Group> = await response.json();
200
-
201
- if (!response.ok) {
202
- setError(result.message || t('groups.serverRemoveError'));
203
- return null;
204
- }
205
-
206
- triggerRefresh();
207
- return result.data || null;
208
- } catch (err) {
209
- setError(err instanceof Error ? err.message : 'Failed to remove server from group');
210
- return null;
211
- }
212
- };
213
-
214
- // Fetch groups when the component mounts or refreshKey changes
215
- useEffect(() => {
216
- fetchGroups();
217
- }, [fetchGroups, refreshKey]);
218
-
219
- return {
220
- groups,
221
- loading,
222
- error,
223
- setError,
224
- triggerRefresh,
225
- createGroup,
226
- updateGroup,
227
- updateGroupServers,
228
- deleteGroup,
229
- addServerToGroup,
230
- removeServerFromGroup
231
- };
232
- };