imcp 0.0.12 → 0.0.14

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 (81) hide show
  1. package/dist/core/ConfigurationProvider.d.ts +2 -1
  2. package/dist/core/ConfigurationProvider.js +20 -24
  3. package/dist/core/InstallationService.d.ts +17 -0
  4. package/dist/core/InstallationService.js +127 -61
  5. package/dist/core/MCPManager.d.ts +1 -0
  6. package/dist/core/MCPManager.js +3 -0
  7. package/dist/core/RequirementService.d.ts +4 -4
  8. package/dist/core/RequirementService.js +11 -7
  9. package/dist/core/ServerSchemaProvider.d.ts +1 -1
  10. package/dist/core/ServerSchemaProvider.js +15 -10
  11. package/dist/core/constants.d.ts +3 -0
  12. package/dist/core/constants.js +4 -1
  13. package/dist/core/installers/clients/ClientInstaller.js +58 -40
  14. package/dist/core/installers/requirements/PipInstaller.js +10 -5
  15. package/dist/core/onboard/FeedOnboardService.d.ts +35 -0
  16. package/dist/core/onboard/FeedOnboardService.js +137 -0
  17. package/dist/core/types.d.ts +6 -1
  18. package/dist/core/validators/FeedValidator.d.ts +13 -0
  19. package/dist/core/validators/FeedValidator.js +27 -0
  20. package/dist/services/ServerService.d.ts +5 -0
  21. package/dist/services/ServerService.js +15 -0
  22. package/dist/utils/githubAuth.js +0 -10
  23. package/dist/utils/githubUtils.d.ts +16 -0
  24. package/dist/utils/githubUtils.js +55 -39
  25. package/dist/web/contract/serverContract.d.ts +64 -0
  26. package/dist/web/contract/serverContract.js +2 -0
  27. package/dist/web/public/css/detailsWidget.css +157 -32
  28. package/dist/web/public/css/onboard.css +44 -0
  29. package/dist/web/public/css/serverDetails.css +35 -19
  30. package/dist/web/public/index.html +16 -10
  31. package/dist/web/public/js/detailsWidget.js +43 -40
  32. package/dist/web/public/js/modal/index.js +58 -0
  33. package/dist/web/public/js/modal/installHandler.js +227 -0
  34. package/dist/web/public/js/modal/installModal.js +163 -0
  35. package/dist/web/public/js/modal/installation.js +281 -0
  36. package/dist/web/public/js/modal/loadingModal.js +52 -0
  37. package/dist/web/public/js/modal/loadingUI.js +74 -0
  38. package/dist/web/public/js/modal/messageQueue.js +112 -0
  39. package/dist/web/public/js/modal/modalSetup.js +512 -0
  40. package/dist/web/public/js/modal/modalUI.js +214 -0
  41. package/dist/web/public/js/modal/modalUtils.js +49 -0
  42. package/dist/web/public/js/modal/version.js +20 -0
  43. package/dist/web/public/js/modal/versionUtils.js +20 -0
  44. package/dist/web/public/js/modal.js +25 -1041
  45. package/dist/web/public/js/onboard/formProcessor.js +309 -0
  46. package/dist/web/public/js/onboard/index.js +131 -0
  47. package/dist/web/public/js/onboard/state.js +32 -0
  48. package/dist/web/public/js/onboard/templates.js +375 -0
  49. package/dist/web/public/js/onboard/uiHandlers.js +196 -0
  50. package/dist/web/public/js/serverCategoryDetails.js +211 -123
  51. package/dist/web/public/onboard.html +150 -0
  52. package/dist/web/server.js +25 -0
  53. package/package.json +3 -4
  54. package/src/core/ConfigurationProvider.ts +37 -29
  55. package/src/core/InstallationService.ts +176 -62
  56. package/src/core/MCPManager.ts +4 -0
  57. package/src/core/RequirementService.ts +12 -8
  58. package/src/core/ServerSchemaLoader.ts +48 -0
  59. package/src/core/ServerSchemaProvider.ts +137 -0
  60. package/src/core/constants.ts +4 -1
  61. package/src/core/installers/clients/ClientInstaller.ts +66 -49
  62. package/src/core/installers/requirements/PipInstaller.ts +10 -5
  63. package/src/core/types.ts +6 -1
  64. package/src/services/ServerService.ts +15 -0
  65. package/src/utils/githubAuth.ts +14 -27
  66. package/src/utils/githubUtils.ts +84 -47
  67. package/src/web/public/css/detailsWidget.css +235 -0
  68. package/src/web/public/css/serverDetails.css +126 -0
  69. package/src/web/public/index.html +16 -10
  70. package/src/web/public/js/detailsWidget.js +264 -0
  71. package/src/web/public/js/modal/index.js +58 -0
  72. package/src/web/public/js/modal/installModal.js +163 -0
  73. package/src/web/public/js/modal/installation.js +281 -0
  74. package/src/web/public/js/modal/loadingModal.js +52 -0
  75. package/src/web/public/js/modal/messageQueue.js +112 -0
  76. package/src/web/public/js/modal/modalSetup.js +512 -0
  77. package/src/web/public/js/modal/modalUtils.js +49 -0
  78. package/src/web/public/js/modal/versionUtils.js +20 -0
  79. package/src/web/public/js/modal.js +25 -1041
  80. package/src/web/public/js/serverCategoryDetails.js +211 -123
  81. package/src/web/server.ts +31 -0
@@ -0,0 +1,64 @@
1
+ import { DependencyConfig, RegistryConfig, ServerInstallOptions } from '../../core/types.js';
2
+ export interface OnboardServerConfig {
3
+ name: string;
4
+ description: string;
5
+ mode: 'stdio' | 'http';
6
+ schemas?: string;
7
+ dependencies?: DependencyConfig;
8
+ repository?: string;
9
+ installation: {
10
+ command: string;
11
+ args?: string[];
12
+ env?: Record<string, {
13
+ name: string;
14
+ default?: string;
15
+ required: boolean;
16
+ description?: string;
17
+ }>;
18
+ };
19
+ }
20
+ export type RequirementType = 'npm' | 'pip' | 'command' | 'extension' | 'other';
21
+ export interface OnboardRequirementConfig {
22
+ type: RequirementType;
23
+ name: string;
24
+ version: string;
25
+ alias?: string;
26
+ registry?: RegistryConfig;
27
+ }
28
+ export interface OnboardRequestBody {
29
+ categoryData: {
30
+ name: string;
31
+ displayName: string;
32
+ description?: string;
33
+ repository?: string;
34
+ requirements?: OnboardRequirementConfig[];
35
+ mcpServers?: OnboardServerConfig[];
36
+ };
37
+ isUpdate: boolean;
38
+ }
39
+ export interface ListQueryParams {
40
+ local?: string;
41
+ }
42
+ export interface UpdateRequirementsRequestBody {
43
+ requirements: {
44
+ name: string;
45
+ updateVersion: string;
46
+ }[];
47
+ }
48
+ export interface InstallServersRequestBody {
49
+ serverList: Record<string, ServerInstallOptions>;
50
+ }
51
+ export interface UninstallServersRequestBody {
52
+ serverList: Record<string, {
53
+ removeData?: boolean;
54
+ }>;
55
+ options: {
56
+ targets: string[];
57
+ removeData?: boolean;
58
+ };
59
+ }
60
+ export interface ApiResponse<T> {
61
+ success: boolean;
62
+ data?: T;
63
+ error?: string;
64
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=serverContract.js.map
@@ -1,30 +1,75 @@
1
1
  .details-widget {
2
2
  transition: all 0.3s ease-in-out;
3
+ width: 100%;
4
+ max-width: 100%;
5
+ box-sizing: border-box;
6
+ margin: 0;
7
+ padding: 0;
8
+ display: block;
9
+ overflow: hidden;
3
10
  }
4
11
 
5
- .tools-grid {
6
- display: grid;
7
- grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
8
- gap: 0.5rem;
9
- padding: 0.5rem;
12
+ .tools-list {
13
+ width: 100%;
14
+ max-width: 100%;
15
+ margin: 0;
16
+ padding: 0.1rem;
17
+ box-sizing: border-box;
18
+ overflow: hidden;
19
+ }
20
+
21
+ .tool-card {
22
+ width: 100%;
23
+ margin-bottom: -1px;
24
+ border-radius: 0;
25
+ box-sizing: border-box;
26
+ }
27
+
28
+ .tool-card:first-child {
29
+ border-top-left-radius: 6px;
30
+ border-top-right-radius: 6px;
31
+ }
32
+
33
+ .tool-card:last-child {
34
+ border-bottom-left-radius: 6px;
35
+ border-bottom-right-radius: 6px;
36
+ margin-bottom: 0;
10
37
  }
11
38
 
12
39
  .tool-card {
13
40
  transition: all 0.3s ease-out;
14
41
  border: 1px solid #e5e7eb;
15
- margin-bottom: 0.5rem;
16
- padding: 0.75rem;
42
+ padding: 0.5rem;
43
+ background-color: white;
44
+ position: relative;
45
+ z-index: 1;
46
+ font-size: 0.9rem;
47
+ width: 100%;
48
+ box-sizing: border-box;
49
+ }
50
+
51
+ .tool-card .text-gray-600 {
52
+ font-size: 0.75rem;
53
+ line-height: 1.3;
17
54
  }
18
55
 
19
56
  .tool-card.active {
20
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
21
- border-left: 4px solid #3b82f6;
57
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.12);
58
+ border-color: transparent;
22
59
  background-color: #f8fafc;
23
60
  }
24
61
 
62
+ .tool-card:hover {
63
+ transform: translateY(-1px);
64
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
65
+ }
66
+
25
67
  .tool-card-header {
26
68
  position: relative;
27
69
  padding-right: 2rem;
70
+ width: 100%;
71
+ box-sizing: border-box;
72
+ cursor: pointer;
28
73
  }
29
74
 
30
75
  .tool-card-header::after {
@@ -49,23 +94,33 @@
49
94
  max-height: 0;
50
95
  opacity: 0;
51
96
  overflow: hidden;
52
- transition: all 0.3s ease-out;
97
+ transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
98
+ background-color: #f9fafb;
99
+ border-radius: 6px;
100
+ width: 100%;
101
+ max-width: 100%;
102
+ box-sizing: border-box;
53
103
  }
54
104
 
55
105
  .tool-details.visible {
56
- max-height: 1500px;
106
+ max-height: 2000px;
57
107
  opacity: 1;
58
- padding-top: 0.75rem;
59
- margin-top: 0.75rem;
108
+ padding: 0.1rem;
109
+ margin-top: 0.5rem;
60
110
  border-top: 1px solid #e5e7eb;
111
+ width: 100%;
112
+ max-width: 100%;
113
+ box-sizing: border-box;
61
114
  }
62
115
 
63
116
  .property-item {
64
- margin-bottom: 0.75rem;
65
- padding-left: 0.75rem;
117
+ margin-bottom: 0.15rem;
118
+ padding: 0.5rem;
66
119
  border-left: 2px solid #e5e7eb;
67
- transition: border-color 0.2s ease;
68
- font-size: 0.9rem;
120
+ transition: all 0.2s ease;
121
+ font-size: 0.8rem;
122
+ background-color: white;
123
+ border-radius: 4px;
69
124
  }
70
125
 
71
126
  .property-item:hover {
@@ -73,38 +128,108 @@
73
128
  }
74
129
 
75
130
  .property-header {
76
- margin-bottom: 0.5rem;
131
+ margin-bottom: 0.25rem;
132
+ }
133
+
134
+ .property-title {
135
+ display: flex;
136
+ align-items: center;
137
+ gap: 0.5rem;
138
+ flex-wrap: wrap;
77
139
  }
78
140
 
79
141
  .property-name {
80
142
  font-weight: 600;
81
143
  color: #1e293b;
144
+ font-size: 0.85rem;
145
+ background-color: #f8fafc;
146
+ padding: 0.2rem 0.4rem;
147
+ border-radius: 4px;
148
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
149
+ display: inline-block;
82
150
  }
83
151
 
84
152
  .property-type {
85
153
  color: #64748b;
86
- font-size: 0.875rem;
154
+ font-size: 0.65rem;
155
+ padding: 0.1rem 0.3rem;
156
+ background: #f1f5f9;
157
+ border-radius: 3px;
158
+ font-family: 'Courier New', monospace;
159
+ margin-left: 0.3rem;
87
160
  }
88
161
 
89
162
  .property-desc {
90
- color: #475569;
91
- font-size: 0.8125rem;
92
- line-height: 1.4;
93
- margin-top: 0.25rem;
163
+ color: #6b7280;
164
+ font-size: 0.7rem;
165
+ margin-left: 0.5rem;
166
+ display: inline-block;
167
+ font-style: italic;
168
+ }
169
+
170
+ .property-default {
171
+ font-size: 0.75rem;
172
+ color: #6b7280;
173
+ margin-top: 0.15rem;
174
+ }
175
+
176
+ .property-default code {
177
+ background: #f1f5f9;
178
+ padding: 0.2rem 0.4rem;
179
+ border-radius: 4px;
180
+ font-family: 'Courier New', monospace;
181
+ font-size: 0.85rem;
94
182
  }
95
183
 
96
184
  .required-fields {
97
- background-color: #fef3c7;
98
- border-left: 4px solid #f59e0b;
99
- padding: 0.5rem 0.75rem;
100
- margin-bottom: 1rem;
101
- font-size: 0.875rem;
185
+ border-left: 2px solid #64748b;
186
+ padding: 0.25rem 0.5rem;
187
+ margin-bottom: 0.5rem;
188
+ font-size: 0.8rem;
189
+ border-radius: 2px;
190
+ color: #64748b;
191
+ }
192
+ .required-star {
193
+ color: #dc2626;
194
+ margin-left: 2px;
195
+ font-weight: bold;
196
+ }
197
+
198
+
199
+ /* Ensure proper container behavior for the widget */
200
+ .details-widget-container {
201
+ width: 100%;
202
+ max-width: 100%;
203
+ box-sizing: border-box;
204
+ position: relative;
205
+ margin: 0;
206
+ padding: 0;
207
+ overflow: hidden;
102
208
  }
103
209
 
104
210
  .nested-properties {
105
- margin-left: 0.75rem;
106
- padding-left: 0.75rem;
211
+ margin: 0.25rem 0 0.25rem 0.5rem;
212
+ padding-left: 0.5rem;
107
213
  border-left: 1px solid #e5e7eb;
108
- margin-top: 0.5rem;
109
- font-size: 0.875rem;
214
+ font-size: 0.8rem;
215
+ }
216
+
217
+ .nested-property-item {
218
+ margin-bottom: 0.5rem;
219
+ padding: 0.25rem 0.5rem;
220
+ }
221
+
222
+ .nested-property-item .property-name {
223
+ font-size: 0.85rem;
224
+ }
225
+
226
+ .nested-property-item .property-type {
227
+ font-size: 0.8rem;
228
+ padding: 0.1rem 0.3rem;
229
+ }
230
+
231
+ .nested-property-item .property-desc {
232
+ font-size: 0.8rem;
233
+ margin-top: 0.25rem;
234
+ color: #64748b;
110
235
  }
@@ -0,0 +1,44 @@
1
+ /* Onboarding form styles */
2
+ .requirement-item,
3
+ .server-item {
4
+ background-color: #ffffff;
5
+ transition: all 0.2s ease;
6
+ }
7
+
8
+ .requirement-item:hover,
9
+ .server-item:hover {
10
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
11
+ }
12
+
13
+ .registry-config,
14
+ .installation-config,
15
+ .env-variables {
16
+ background-color: #f9fafb;
17
+ border-radius: 0.5rem;
18
+ padding: 1rem;
19
+ margin-top: 1rem;
20
+ }
21
+
22
+ .registry-github,
23
+ .registry-artifacts {
24
+ background-color: #ffffff;
25
+ border-radius: 0.5rem;
26
+ padding: 1rem;
27
+ }
28
+
29
+ /* Order field styling */
30
+ input[type="number"][name$=".order"] {
31
+ -moz-appearance: textfield;
32
+ }
33
+
34
+ input[type="number"][name$=".order"]::-webkit-outer-spin-button,
35
+ input[type="number"][name$=".order"]::-webkit-inner-spin-button {
36
+ -webkit-appearance: none;
37
+ margin: 0;
38
+ }
39
+
40
+ input[type="number"][name$=".order"]:focus {
41
+ border-color: #3b82f6;
42
+ outline: none;
43
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
44
+ }
@@ -1,24 +1,24 @@
1
1
  /* Server item container */
2
- .server-item {
2
+ .server-item-content {
3
3
  cursor: pointer;
4
4
  position: relative;
5
5
  transition: all 0.2s ease;
6
- }
7
-
8
- .server-item-content {
9
- position: relative;
10
6
  border: 1px solid #e5e7eb;
11
7
  border-radius: 0.5rem;
12
8
  padding: 1rem;
13
9
  padding-right: calc(120px + 3rem); /* Button width + spacing */
14
- margin-bottom: 1rem;
10
+ box-sizing: border-box;
15
11
  background-color: #ffffff;
16
- transition: all 0.2s ease;
12
+ z-index: 1;
13
+ margin-bottom: 1rem;
14
+ width: 100%;
15
+ max-width: 100%;
16
+ overflow: visible;
17
17
  }
18
18
 
19
- .server-item:hover .server-item-content {
20
- border-color: #3b82f6;
21
- box-shadow: 0 2px 4px rgba(59, 130, 246, 0.1);
19
+ .server-item-content:hover {
20
+ border-color: transparent;
21
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
22
22
  transform: translateY(-1px);
23
23
  }
24
24
 
@@ -29,20 +29,33 @@
29
29
  transition: max-height 0.3s ease-out;
30
30
  background-color: #f8fafc;
31
31
  border-radius: 0 0 0.5rem 0.5rem;
32
- margin-top: -1rem;
33
- margin-bottom: 1rem;
32
+ margin: -1px 0 0;
34
33
  border: 1px solid #e5e7eb;
35
34
  border-top: none;
35
+ position: relative;
36
+ z-index: 0;
37
+ width: 100%;
38
+ max-width: 100%;
39
+ box-sizing: border-box;
40
+ left: 0;
41
+ right: 0;
36
42
  }
37
43
 
38
44
  .details-widget.expanded {
39
- max-height: 800px; /* Increased height to accommodate more content */
40
- border-color: #3b82f6;
41
- transition: max-height 0.3s ease-in-out;
45
+ max-height: 2000px; /* Increased height to accommodate more content */
46
+ border-color: transparent;
47
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
48
+ transition: max-height 0.3s ease-in-out, box-shadow 0.2s ease;
49
+ width: 100%;
50
+ margin-left: 0;
51
+ margin-right: 0;
52
+ display: block;
42
53
  }
43
54
 
44
55
  .details-widget-content {
45
56
  padding: 1rem;
57
+ width: 100%;
58
+ box-sizing: border-box;
46
59
  }
47
60
 
48
61
  .description-text {
@@ -53,9 +66,12 @@
53
66
 
54
67
  /* Expand/collapse animation */
55
68
  .server-item-content.expanded {
69
+ border-bottom: none;
56
70
  border-bottom-left-radius: 0;
57
71
  border-bottom-right-radius: 0;
58
- border-color: #3b82f6;
72
+ border-color: transparent;
73
+ box-shadow: 0 -1px 8px rgba(0, 0, 0, 0.08);
74
+ margin-bottom: 0;
59
75
  }
60
76
 
61
77
  /* Server item layout */
@@ -84,13 +100,13 @@
84
100
  .action-buttons {
85
101
  position: absolute;
86
102
  right: 1rem;
87
- top: 50%;
88
- transform: translateY(-50%);
103
+ top: calc(2rem + 0.5rem); /* Align with description text (header height + margin-bottom) */
89
104
  margin: 0;
105
+ z-index: 2; /* Ensure buttons stay on top */
90
106
  }
91
107
 
92
108
  .action-buttons button {
93
- min-width: 120px;
109
+ min-width: 100px;
94
110
  padding: 0.5rem 1.5rem;
95
111
  text-align: center;
96
112
  font-weight: 600;
@@ -12,6 +12,8 @@
12
12
  <link rel="stylesheet" href="styles.css">
13
13
  <link rel="stylesheet" href="css/modal.css">
14
14
  <link rel="stylesheet" href="css/notifications.css">
15
+ <link rel="stylesheet" href="css/serverDetails.css">
16
+ <link rel="stylesheet" href="css/detailsWidget.css">
15
17
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
16
18
 
17
19
  <!-- Alert container for notifications -->
@@ -160,19 +162,23 @@
160
162
  setupSearch();
161
163
  setupModalOutsideClick();
162
164
 
163
- // Check URL parameters for category
164
- const urlParams = new URLSearchParams(window.location.search);
165
- const categoryParam = urlParams.get('category');
165
+ try {
166
+ // First fetch categories and wait for completion
167
+ await fetchServerCategories();
166
168
 
167
- // If we have a category parameter or last selected category
168
- const lastSelected = categoryParam || localStorage.getItem('lastSelectedCategory');
169
+ // Check URL parameters for category
170
+ const urlParams = new URLSearchParams(window.location.search);
171
+ const categoryParam = urlParams.get('category');
169
172
 
170
- // First fetch categories
171
- await fetchServerCategories();
173
+ // If we have a category parameter or last selected category
174
+ const lastSelected = categoryParam || localStorage.getItem('lastSelectedCategory');
172
175
 
173
- // Then show the selected category if it exists
174
- if (lastSelected) {
175
- showServerDetails(lastSelected);
176
+ // Only show details after data is loaded
177
+ if (lastSelected) {
178
+ await showServerDetails(lastSelected);
179
+ }
180
+ } catch (error) {
181
+ console.error('Error during initialization:', error);
176
182
  }
177
183
  });
178
184
  </script>
@@ -12,14 +12,33 @@ export class DetailsWidget {
12
12
  link.rel = 'stylesheet';
13
13
  link.href = '/css/detailsWidget.css';
14
14
  document.head.appendChild(link);
15
+ // Create wrapper to maintain proper width alignment
16
+ this.containerWrapper = document.createElement('div');
17
+ this.containerWrapper.className = 'details-widget-container';
18
+ this.containerWrapper.style.width = '100%';
19
+ this.containerWrapper.style.boxSizing = 'border-box';
20
+ this.containerWrapper.style.maxWidth = '100%';
21
+ this.containerWrapper.style.overflow = 'hidden';
15
22
 
23
+ // Create the widget element
16
24
  this.widgetElement = document.createElement('div');
17
25
  this.widgetElement.className = 'details-widget';
18
- this.widgetElement.style.overflow = 'auto'; // Enable scrolling
26
+ this.widgetElement.style.width = '100%';
27
+ this.widgetElement.style.boxSizing = 'border-box';
28
+ this.widgetElement.style.maxWidth = '100%';
29
+
30
+ // Create the content element
19
31
  this.contentElement = document.createElement('div');
20
32
  this.contentElement.className = 'details-widget-content';
33
+ this.contentElement.style.width = '100%';
34
+ this.contentElement.style.boxSizing = 'border-box';
35
+
36
+ // Build the DOM structure
21
37
  this.widgetElement.appendChild(this.contentElement);
22
- this.container.appendChild(this.widgetElement);
38
+ this.containerWrapper.appendChild(this.widgetElement);
39
+
40
+ // Insert after the server item while maintaining proper structure
41
+ this.container.after(this.containerWrapper);
23
42
  }
24
43
 
25
44
  setContent(content) {
@@ -54,16 +73,24 @@ export class DetailsWidget {
54
73
  expand() {
55
74
  this.isExpanded = true;
56
75
  this.widgetElement.classList.add('expanded');
57
- if (this.container.querySelector('.server-item-content')) {
58
- this.container.querySelector('.server-item-content').classList.add('expanded');
76
+
77
+ // Ensure proper dimensions based on container
78
+ const containerWidth = this.container.offsetWidth;
79
+ this.containerWrapper.style.width = `${containerWidth}px`;
80
+ this.containerWrapper.style.maxWidth = '100%';
81
+ this.containerWrapper.style.display = 'block';
82
+
83
+ // Add expanded state to container
84
+ if (this.container) {
85
+ this.container.classList.add('expanded');
59
86
  }
60
87
  }
61
88
 
62
89
  collapse() {
63
90
  this.isExpanded = false;
64
91
  this.widgetElement.classList.remove('expanded');
65
- if (this.container.querySelector('.server-item-content')) {
66
- this.container.querySelector('.server-item-content').classList.remove('expanded');
92
+ if (this.container) {
93
+ this.container.classList.remove('expanded');
67
94
  }
68
95
  // Reset expanded tool state
69
96
  this.expandedTool = null;
@@ -76,22 +103,20 @@ export class DetailsWidget {
76
103
  }
77
104
 
78
105
  let html = `
79
- <div class="tools-list p-2">
80
- <div class="tools-grid grid gap-2">
106
+ <div class="tools-list">
81
107
  `;
82
108
 
83
109
  Object.entries(schemaContent).forEach(([toolName, toolInfo]) => {
84
110
  if (!toolInfo) return;
85
111
 
86
- html += `
87
- <div class="tool-card" data-tool="${this.escapeHtml(toolName)}">
112
+ html += `<div class="tool-card" data-tool="${this.escapeHtml(toolName)}">
88
113
  <div class="tool-card-header">
89
- <div class="tool-header mb-2">
114
+ <div class="tool-header">
90
115
  <h3 class="text-md font-semibold text-blue-600">${toolInfo.name || toolName}</h3>
116
+ <div class="text-gray-600 text-sm">${toolInfo.description || 'No description available'}</div>
91
117
  </div>
92
- <p class="text-gray-700 text-sm">${toolInfo.description || 'No description available'}</p>
93
118
  </div>
94
- <div class="tool-details hidden mt-3" data-tool-details="${this.escapeHtml(toolName)}">
119
+ <div class="tool-details hidden" data-tool-details="${this.escapeHtml(toolName)}">
95
120
  ${this.renderInputSchema(toolInfo.inputSchema)}
96
121
  </div>
97
122
  </div>
@@ -99,7 +124,6 @@ export class DetailsWidget {
99
124
  });
100
125
 
101
126
  html += `
102
- </div>
103
127
  </div>
104
128
  `;
105
129
 
@@ -170,17 +194,6 @@ export class DetailsWidget {
170
194
  let html = '<div class="properties-list">';
171
195
 
172
196
  try {
173
- // Required fields banner
174
- if (schema.required?.length > 0) {
175
- html += `
176
- <div class="required-fields mb-3 bg-yellow-50 p-2 rounded">
177
- <span class="text-sm font-medium text-yellow-800">
178
- Required: ${schema.required.join(', ')}
179
- </span>
180
- </div>
181
- `;
182
- }
183
-
184
197
  // Render each property
185
198
  Object.entries(schema.properties).forEach(([propName, propDetails]) => {
186
199
  if (!propDetails) return;
@@ -188,17 +201,11 @@ export class DetailsWidget {
188
201
  const isRequired = schema.required?.includes(propName);
189
202
  const type = this.getPropertyType(propDetails);
190
203
 
191
- html += `
192
- <div class="property-item ${isRequired ? 'required' : ''}">
204
+ html += `<div class="property-item ${isRequired ? 'required' : ''}">
193
205
  <div class="property-header">
194
- <span class="property-name">${this.escapeHtml(propName)}</span>
195
- <span class="property-type">${this.escapeHtml(type)}</span>
196
- ${isRequired ? '<span class="required-badge">Required</span>' : ''}
206
+ <span class="property-name">${this.escapeHtml(propName)}${isRequired ? '<span class="required-star">*</span>' : ''}</span><span class="property-type">${this.escapeHtml(type)}</span>${propDetails.description ? `<span class="property-desc">${this.escapeHtml(propDetails.description)}</span>` : ''}
207
+ ${propDetails.default !== undefined ? `<div class="property-default">Default: <code>${this.escapeHtml(JSON.stringify(propDetails.default))}</code></div>` : ''}
197
208
  </div>
198
- ${propDetails.description ?
199
- `<p class="property-desc">${this.escapeHtml(propDetails.description)}</p>` : ''}
200
- ${propDetails.default !== undefined ?
201
- `<p class="property-default">Default: ${this.escapeHtml(JSON.stringify(propDetails.default))}</p>` : ''}
202
209
  ${this.renderNestedProperties(propDetails)}
203
210
  </div>
204
211
  `;
@@ -218,12 +225,8 @@ export class DetailsWidget {
218
225
  const type = this.getPropertyType(details);
219
226
  html += `
220
227
  <div class="nested-property-item">
221
- <div class="property-header">
222
- <span class="property-name">${this.escapeHtml(name)}</span>
223
- <span class="property-type">${this.escapeHtml(type)}</span>
224
- </div>
225
- ${details.description ?
226
- `<p class="property-desc">${this.escapeHtml(details.description)}</p>` : ''}
228
+ <span class="property-name">${this.escapeHtml(name)}</span><span class="property-type">${this.escapeHtml(type)}</span>
229
+ ${details.description ? `<div class="property-desc">${this.escapeHtml(details.description)}</div>` : ''}
227
230
  </div>
228
231
  `;
229
232
  });