imcp 0.0.14 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/ConfigurationProvider.d.ts +1 -0
- package/dist/core/ConfigurationProvider.js +15 -0
- package/dist/core/InstallationService.js +2 -7
- package/dist/core/MCPManager.d.ts +11 -2
- package/dist/core/MCPManager.js +24 -1
- package/dist/core/RequirementService.js +2 -8
- package/dist/core/installers/clients/BaseClientInstaller.d.ts +51 -0
- package/dist/core/installers/clients/BaseClientInstaller.js +160 -0
- package/dist/core/installers/clients/ClientInstaller.d.ts +16 -9
- package/dist/core/installers/clients/ClientInstaller.js +80 -527
- package/dist/core/installers/clients/ClientInstallerFactory.d.ts +20 -0
- package/dist/core/installers/clients/ClientInstallerFactory.js +37 -0
- package/dist/core/installers/clients/ClineInstaller.d.ts +18 -0
- package/dist/core/installers/clients/ClineInstaller.js +124 -0
- package/dist/core/installers/clients/GithubCopilotInstaller.d.ts +34 -0
- package/dist/core/installers/clients/GithubCopilotInstaller.js +162 -0
- package/dist/core/installers/clients/MSRooCodeInstaller.d.ts +15 -0
- package/dist/core/installers/clients/MSRooCodeInstaller.js +122 -0
- package/dist/core/installers/requirements/BaseInstaller.d.ts +11 -34
- package/dist/core/installers/requirements/BaseInstaller.js +5 -116
- package/dist/core/installers/requirements/CommandInstaller.d.ts +6 -1
- package/dist/core/installers/requirements/CommandInstaller.js +7 -0
- package/dist/core/installers/requirements/GeneralInstaller.d.ts +6 -1
- package/dist/core/installers/requirements/GeneralInstaller.js +9 -4
- package/dist/core/installers/requirements/NpmInstaller.d.ts +46 -7
- package/dist/core/installers/requirements/NpmInstaller.js +150 -58
- package/dist/core/installers/requirements/PipInstaller.d.ts +9 -0
- package/dist/core/installers/requirements/PipInstaller.js +66 -28
- package/dist/core/onboard/FeedOnboardService.d.ts +50 -13
- package/dist/core/onboard/FeedOnboardService.js +263 -88
- package/dist/core/onboard/OnboardProcessor.d.ts +79 -0
- package/dist/core/onboard/OnboardProcessor.js +290 -0
- package/dist/core/onboard/OnboardStatus.d.ts +49 -0
- package/dist/core/onboard/OnboardStatus.js +10 -0
- package/dist/core/onboard/OnboardStatusManager.d.ts +57 -0
- package/dist/core/onboard/OnboardStatusManager.js +176 -0
- package/dist/core/types.d.ts +4 -5
- package/dist/core/validators/FeedValidator.d.ts +8 -1
- package/dist/core/validators/FeedValidator.js +60 -7
- package/dist/core/validators/IServerValidator.d.ts +19 -0
- package/dist/core/validators/IServerValidator.js +2 -0
- package/dist/core/validators/SSEServerValidator.d.ts +15 -0
- package/dist/core/validators/SSEServerValidator.js +39 -0
- package/dist/core/validators/ServerValidatorFactory.d.ts +24 -0
- package/dist/core/validators/ServerValidatorFactory.js +45 -0
- package/dist/core/validators/StdioServerValidator.d.ts +46 -0
- package/dist/core/validators/StdioServerValidator.js +229 -0
- package/dist/services/InstallRequestValidator.d.ts +1 -1
- package/dist/services/ServerService.d.ts +9 -6
- package/dist/services/ServerService.js +18 -7
- package/dist/utils/adoUtils.d.ts +29 -0
- package/dist/utils/adoUtils.js +252 -0
- package/dist/utils/clientUtils.d.ts +0 -7
- package/dist/utils/clientUtils.js +0 -42
- package/dist/utils/githubUtils.d.ts +10 -0
- package/dist/utils/githubUtils.js +22 -0
- package/dist/utils/macroExpressionUtils.d.ts +38 -0
- package/dist/utils/macroExpressionUtils.js +116 -0
- package/dist/utils/osUtils.d.ts +4 -20
- package/dist/utils/osUtils.js +78 -23
- package/dist/web/contract/serverContract.d.ts +3 -1
- package/dist/web/public/css/notifications.css +48 -17
- package/dist/web/public/css/onboard.css +66 -3
- package/dist/web/public/index.html +84 -16
- package/dist/web/public/js/api.js +3 -6
- package/dist/web/public/js/flights/flights.js +127 -0
- package/dist/web/public/js/modal/installation.js +5 -5
- package/dist/web/public/js/modal/modalSetup.js +3 -2
- package/dist/web/public/js/notifications.js +66 -27
- package/dist/web/public/js/onboard/ONBOARDING_PAGE_DESIGN.md +338 -0
- package/dist/web/public/js/onboard/formProcessor.js +810 -255
- package/dist/web/public/js/onboard/index.js +328 -85
- package/dist/web/public/js/onboard/publishHandler.js +132 -0
- package/dist/web/public/js/onboard/state.js +61 -17
- package/dist/web/public/js/onboard/templates.js +217 -249
- package/dist/web/public/js/onboard/uiHandlers.js +679 -117
- package/dist/web/public/js/onboard/validationHandlers.js +378 -0
- package/dist/web/public/js/serverCategoryList.js +15 -2
- package/dist/web/public/onboard.html +191 -45
- package/dist/web/public/styles.css +91 -1
- package/dist/web/server.d.ts +0 -10
- package/dist/web/server.js +131 -22
- package/package.json +2 -2
- package/src/core/ConfigurationProvider.ts +15 -0
- package/src/core/InstallationService.ts +2 -7
- package/src/core/MCPManager.ts +26 -1
- package/src/core/RequirementService.ts +2 -9
- package/src/core/installers/clients/BaseClientInstaller.ts +196 -0
- package/src/core/installers/clients/ClientInstaller.ts +97 -608
- package/src/core/installers/clients/ClientInstallerFactory.ts +43 -0
- package/src/core/installers/clients/ClineInstaller.ts +135 -0
- package/src/core/installers/clients/GithubCopilotInstaller.ts +179 -0
- package/src/core/installers/clients/MSRooCodeInstaller.ts +133 -0
- package/src/core/installers/requirements/BaseInstaller.ts +13 -136
- package/src/core/installers/requirements/CommandInstaller.ts +9 -1
- package/src/core/installers/requirements/GeneralInstaller.ts +11 -4
- package/src/core/installers/requirements/NpmInstaller.ts +178 -61
- package/src/core/installers/requirements/PipInstaller.ts +68 -29
- package/src/core/onboard/FeedOnboardService.ts +346 -0
- package/src/core/onboard/OnboardProcessor.ts +305 -0
- package/src/core/onboard/OnboardStatus.ts +55 -0
- package/src/core/onboard/OnboardStatusManager.ts +188 -0
- package/src/core/types.ts +4 -5
- package/src/core/validators/FeedValidator.ts +79 -0
- package/src/core/validators/IServerValidator.ts +21 -0
- package/src/core/validators/SSEServerValidator.ts +43 -0
- package/src/core/validators/ServerValidatorFactory.ts +51 -0
- package/src/core/validators/StdioServerValidator.ts +259 -0
- package/src/services/InstallRequestValidator.ts +1 -1
- package/src/services/ServerService.ts +22 -7
- package/src/utils/adoUtils.ts +291 -0
- package/src/utils/clientUtils.ts +0 -44
- package/src/utils/githubUtils.ts +24 -0
- package/src/utils/macroExpressionUtils.ts +121 -0
- package/src/utils/osUtils.ts +89 -24
- package/src/web/contract/serverContract.ts +74 -0
- package/src/web/public/css/notifications.css +48 -17
- package/src/web/public/css/onboard.css +107 -0
- package/src/web/public/index.html +84 -16
- package/src/web/public/js/api.js +3 -6
- package/src/web/public/js/flights/flights.js +127 -0
- package/src/web/public/js/modal/installation.js +5 -5
- package/src/web/public/js/modal/modalSetup.js +3 -2
- package/src/web/public/js/notifications.js +66 -27
- package/src/web/public/js/onboard/ONBOARDING_PAGE_DESIGN.md +338 -0
- package/src/web/public/js/onboard/formProcessor.js +864 -0
- package/src/web/public/js/onboard/index.js +374 -0
- package/src/web/public/js/onboard/publishHandler.js +132 -0
- package/src/web/public/js/onboard/state.js +76 -0
- package/src/web/public/js/onboard/templates.js +343 -0
- package/src/web/public/js/onboard/uiHandlers.js +758 -0
- package/src/web/public/js/onboard/validationHandlers.js +378 -0
- package/src/web/public/js/serverCategoryList.js +15 -2
- package/src/web/public/onboard.html +296 -0
- package/src/web/public/styles.css +91 -1
- package/src/web/server.ts +167 -58
|
@@ -6,13 +6,45 @@
|
|
|
6
6
|
<title>Onboard MCP Category - IMCP</title>
|
|
7
7
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
8
8
|
<link href="https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css" rel="stylesheet">
|
|
9
|
-
|
|
9
|
+
<!-- Bootstrap CSS is likely not needed if primarily using Tailwind -->
|
|
10
|
+
<!-- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> -->
|
|
10
11
|
<link rel="stylesheet" href="styles.css">
|
|
11
12
|
<link rel="stylesheet" href="css/onboard.css">
|
|
13
|
+
<!-- Highlight.js for JSON syntax highlighting -->
|
|
14
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
|
|
15
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
|
12
16
|
<link rel="stylesheet" href="css/modal.css">
|
|
13
17
|
<link rel="stylesheet" href="css/notifications.css">
|
|
18
|
+
<script type="module">
|
|
19
|
+
import flights, { getFlightQueryParameters } from './js/flights/flights.js';
|
|
20
|
+
if (!flights.enableOnboard) {
|
|
21
|
+
// Preserve flight params when redirecting
|
|
22
|
+
window.location.href = `index.html${getFlightQueryParameters()}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
26
|
+
const flightQueryString = getFlightQueryParameters();
|
|
27
|
+
|
|
28
|
+
const backToServerLink = document.querySelector('a[href="index.html"]');
|
|
29
|
+
if (backToServerLink) {
|
|
30
|
+
backToServerLink.href = `index.html${flightQueryString}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Update cancel buttons in forms
|
|
34
|
+
const cancelButtons = document.querySelectorAll('button[onclick="window.location.href=\'index.html\'"]');
|
|
35
|
+
cancelButtons.forEach(button => {
|
|
36
|
+
button.onclick = () => { window.location.href = `index.html${flightQueryString}`; };
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const jsonEditorCancelButton = document.querySelector('#jsonEditorActionsContainer button[onclick="window.location.href=\'index.html\'"]');
|
|
40
|
+
if (jsonEditorCancelButton) {
|
|
41
|
+
jsonEditorCancelButton.onclick = () => { window.location.href = `index.html${flightQueryString}`; };
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
</script>
|
|
14
45
|
</head>
|
|
15
46
|
<body class="bg-gray-50 min-h-screen">
|
|
47
|
+
<div class="alert-container"></div>
|
|
16
48
|
<div class="container mx-auto px-4 py-6">
|
|
17
49
|
<div class="flex items-center justify-between mb-8">
|
|
18
50
|
<h1 class="text-3xl font-bold text-gray-900 flex items-center">
|
|
@@ -25,7 +57,7 @@
|
|
|
25
57
|
</a>
|
|
26
58
|
</div>
|
|
27
59
|
|
|
28
|
-
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-
|
|
60
|
+
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 max-w-6xl mx-auto">
|
|
29
61
|
<!-- Tab Navigation -->
|
|
30
62
|
<div class="mb-6 border-b border-gray-200">
|
|
31
63
|
<nav class="flex space-x-8" aria-label="Tabs">
|
|
@@ -36,115 +68,229 @@
|
|
|
36
68
|
Create New Server in Existing Category
|
|
37
69
|
</button>
|
|
38
70
|
</nav>
|
|
71
|
+
<!-- View Mode Toggle Switch -->
|
|
72
|
+
<div class="flex justify-end mt-2 mb-4">
|
|
73
|
+
<label for="viewModeToggle" class="flex items-center cursor-pointer">
|
|
74
|
+
<span class="mr-3 text-sm font-medium text-gray-700">Form View</span>
|
|
75
|
+
<div class="relative">
|
|
76
|
+
<input type="checkbox" id="viewModeToggle" class="sr-only peer">
|
|
77
|
+
<div class="w-10 h-6 bg-gray-200 rounded-full peer peer-focus:ring-2 peer-focus:ring-blue-300 peer-checked:bg-blue-600 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all"></div>
|
|
78
|
+
</div>
|
|
79
|
+
<span class="ml-3 text-sm font-medium text-gray-700">JSON View</span>
|
|
80
|
+
</label>
|
|
81
|
+
</div>
|
|
39
82
|
</div>
|
|
40
83
|
<!-- Tab Panels -->
|
|
41
84
|
<div id="panel-create-category">
|
|
42
|
-
<form id="onboardForm" class="space-y-
|
|
85
|
+
<form id="onboardForm" class="space-y-6">
|
|
43
86
|
<!-- Basic Information -->
|
|
44
87
|
<div class="space-y-4">
|
|
45
|
-
<h2 class="text-xl font-semibold text-gray-900 flex items-center mb-4">
|
|
46
|
-
<
|
|
47
|
-
|
|
88
|
+
<h2 onclick="toggleSectionContent('basicInformationContent', this.querySelector('.toggle-icon'))" class="text-xl font-semibold text-gray-900 flex items-center justify-between mb-4 cursor-pointer">
|
|
89
|
+
<span class="flex items-center">
|
|
90
|
+
<i class='bx bx-info-circle mr-2 text-blue-600'></i>
|
|
91
|
+
Basic Information
|
|
92
|
+
</span>
|
|
93
|
+
<i class='bx bx-chevron-down toggle-icon text-xl text-gray-500'></i>
|
|
48
94
|
</h2>
|
|
49
|
-
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
95
|
+
<div id="basicInformationContent" class="grid grid-cols-1 md:grid-cols-2 gap-4 p-6 bg-white rounded-lg border border-gray-200 shadow-sm">
|
|
50
96
|
<div>
|
|
51
97
|
<label class="block text-sm font-medium text-gray-700 mb-1">Category Name*</label>
|
|
52
98
|
<input type="text" name="name" required
|
|
53
|
-
class="w-full px-3 py-
|
|
99
|
+
class="w-full px-3 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
54
100
|
placeholder="e.g., ai-coder-tools">
|
|
55
101
|
</div>
|
|
56
102
|
<div>
|
|
57
103
|
<label class="block text-sm font-medium text-gray-700 mb-1">Display Name*</label>
|
|
58
104
|
<input type="text" name="displayName" required
|
|
59
|
-
class="w-full px-3 py-
|
|
105
|
+
class="w-full px-3 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
60
106
|
placeholder="e.g., Coder Tools">
|
|
61
107
|
</div>
|
|
62
108
|
<div class="md:col-span-2">
|
|
63
109
|
<label class="block text-sm font-medium text-gray-700 mb-1">Description</label>
|
|
64
110
|
<textarea name="description" rows="3"
|
|
65
|
-
class="w-full px-3 py-
|
|
111
|
+
class="w-full px-3 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
66
112
|
placeholder="Describe the purpose and capabilities of this server category"></textarea>
|
|
67
113
|
</div>
|
|
68
114
|
<div class="md:col-span-2">
|
|
69
115
|
<label class="block text-sm font-medium text-gray-700 mb-1">Repository URL</label>
|
|
70
116
|
<input type="url" name="repository"
|
|
71
|
-
class="w-full px-3 py-
|
|
117
|
+
class="w-full px-3 py-1.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
72
118
|
placeholder="e.g., https://github.com/organization/repository">
|
|
73
119
|
</div>
|
|
74
120
|
</div>
|
|
75
121
|
</div>
|
|
76
|
-
<!-- MCP Servers
|
|
122
|
+
<!-- MCP Servers -->
|
|
77
123
|
<div class="space-y-4">
|
|
78
|
-
<
|
|
79
|
-
<
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
124
|
+
<div class="flex justify-between items-center mb-4">
|
|
125
|
+
<h2 class="text-xl font-semibold text-gray-900 flex items-center">
|
|
126
|
+
<i class='bx bx-server mr-2 text-blue-600'></i>
|
|
127
|
+
MCP Servers
|
|
128
|
+
</h2>
|
|
129
|
+
<button type="button" onclick="addServer()"
|
|
130
|
+
class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 flex items-center text-sm">
|
|
131
|
+
<i class='bx bx-plus mr-2'></i>
|
|
132
|
+
Add MCP Server
|
|
133
|
+
</button>
|
|
134
|
+
</div>
|
|
135
|
+
<div id="serversList" class="space-y-4">
|
|
136
|
+
<!-- Server configurations will be added here dynamically by serverTemplate -->
|
|
84
137
|
</div>
|
|
85
|
-
<button type="button" onclick="addServer()"
|
|
86
|
-
class="px-4 py-2 border border-gray-300 rounded-lg text-gray-600 hover:bg-gray-50 flex items-center">
|
|
87
|
-
<i class='bx bx-plus mr-2'></i>
|
|
88
|
-
Add Server
|
|
89
|
-
</button>
|
|
90
138
|
</div>
|
|
91
139
|
<div class="flex justify-end space-x-4 pt-6 border-t">
|
|
92
140
|
<button type="button" onclick="window.location.href='index.html'"
|
|
93
141
|
class="px-6 py-2.5 border border-gray-300 rounded-lg text-gray-600 hover:bg-gray-50">
|
|
94
142
|
Cancel
|
|
95
143
|
</button>
|
|
96
|
-
<button type="
|
|
144
|
+
<button type="button" id="validateButtonNewCategory"
|
|
145
|
+
class="px-6 py-2.5 bg-green-500 text-white rounded-lg hover:bg-green-600 flex items-center">
|
|
146
|
+
<i class='bx bx-check-shield mr-2'></i>
|
|
147
|
+
Validate
|
|
148
|
+
</button>
|
|
149
|
+
<button type="submit" id="publishButtonNewCategory"
|
|
97
150
|
class="px-6 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 flex items-center">
|
|
98
|
-
<i class='bx
|
|
99
|
-
|
|
151
|
+
<i class='bx bxs-cloud-upload mr-2'></i>
|
|
152
|
+
Publish
|
|
100
153
|
</button>
|
|
101
154
|
</div>
|
|
155
|
+
<!-- Validation Status Panel -->
|
|
156
|
+
<div id="validationStatusPanelNewCategory" class="hidden p-6 bg-gray-50 rounded-lg border border-gray-200">
|
|
157
|
+
<h3 onclick="toggleSectionContent('validationStatusContentNewCategory', this.querySelector('.toggle-icon'))" class="cursor-pointer text-lg font-semibold text-gray-800 mb-3 flex items-center justify-between">
|
|
158
|
+
<span class="flex items-center">
|
|
159
|
+
<i class='bx bx-analyse mr-2 text-blue-600'></i>Validation Status
|
|
160
|
+
</span>
|
|
161
|
+
<i class='bx bx-chevron-down toggle-icon text-xl text-gray-500'></i>
|
|
162
|
+
</h3>
|
|
163
|
+
<div id="validationStatusContentNewCategory" class="text-sm text-gray-700 space-y-2">
|
|
164
|
+
<!-- Validation messages will be displayed here -->
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
102
167
|
</form>
|
|
103
168
|
</div>
|
|
104
169
|
<div id="panel-create-server" class="hidden">
|
|
105
|
-
<form id="onboardServerForm" class="space-y-
|
|
170
|
+
<form id="onboardServerForm" class="space-y-6">
|
|
106
171
|
<!-- Select Existing Category -->
|
|
107
172
|
<div class="space-y-4">
|
|
108
173
|
<h2 class="text-xl font-semibold text-gray-900 flex items-center mb-4">
|
|
109
174
|
<i class='bx bx-category mr-2 text-blue-600'></i>
|
|
110
175
|
Select Server Category
|
|
111
176
|
</h2>
|
|
112
|
-
<select id="existingCategorySelect" name="
|
|
177
|
+
<select id="existingCategorySelect" name="categoryName" required
|
|
113
178
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
|
114
|
-
<option value="">Loading...</option>
|
|
179
|
+
<option value="">Loading categories...</option>
|
|
115
180
|
</select>
|
|
116
181
|
</div>
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
182
|
+
|
|
183
|
+
<!-- Basic Information (Read-only after category selection) -->
|
|
184
|
+
<div id="existingCategoryBasicInfoContainer" class="hidden space-y-4">
|
|
185
|
+
<h2 onclick="toggleSectionContent('existingCategoryBasicInformationContent', this.querySelector('.toggle-icon'))" class="text-xl font-semibold text-gray-900 flex items-center justify-between mb-4 cursor-pointer">
|
|
186
|
+
<span class="flex items-center">
|
|
187
|
+
<i class='bx bx-info-circle mr-2 text-blue-600'></i>
|
|
188
|
+
Basic Information (Read-only)
|
|
189
|
+
</span>
|
|
190
|
+
<i class='bx bx-chevron-down toggle-icon text-xl text-gray-500'></i>
|
|
122
191
|
</h2>
|
|
123
|
-
<
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
192
|
+
<div id="existingCategoryBasicInformationContent" class="grid grid-cols-1 md:grid-cols-2 gap-4 p-6 bg-white rounded-lg border border-gray-200 shadow-sm">
|
|
193
|
+
<div>
|
|
194
|
+
<label class="block text-sm font-medium text-gray-700 mb-1">Category Name</label>
|
|
195
|
+
<input type="text" name="name" readonly class="w-full px-3 py-1.5 border border-gray-300 rounded-lg bg-gray-100 cursor-not-allowed">
|
|
196
|
+
</div>
|
|
197
|
+
<div>
|
|
198
|
+
<label class="block text-sm font-medium text-gray-700 mb-1">Display Name</label>
|
|
199
|
+
<input type="text" name="displayName" readonly class="w-full px-3 py-1.5 border border-gray-300 rounded-lg bg-gray-100 cursor-not-allowed">
|
|
200
|
+
</div>
|
|
201
|
+
<div class="md:col-span-2">
|
|
202
|
+
<label class="block text-sm font-medium text-gray-700 mb-1">Description</label>
|
|
203
|
+
<textarea name="description" rows="3" readonly class="w-full px-3 py-1.5 border border-gray-300 rounded-lg bg-gray-100 cursor-not-allowed"></textarea>
|
|
204
|
+
</div>
|
|
205
|
+
<div class="md:col-span-2">
|
|
206
|
+
<label class="block text-sm font-medium text-gray-700 mb-1">Repository URL</label>
|
|
207
|
+
<input type="url" name="repository" readonly class="w-full px-3 py-1.5 border border-gray-300 rounded-lg bg-gray-100 cursor-not-allowed">
|
|
208
|
+
</div>
|
|
209
|
+
</div>
|
|
128
210
|
</div>
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
211
|
+
|
|
212
|
+
<!-- MCP Servers (Existing read-only, new ones editable) -->
|
|
213
|
+
<div id="existingCategoryMcpServersContainer" class="hidden space-y-4">
|
|
214
|
+
<div class="flex justify-between items-center mb-4">
|
|
215
|
+
<h2 class="text-xl font-semibold text-gray-900 flex items-center">
|
|
216
|
+
<i class='bx bx-server mr-2 text-blue-600'></i>
|
|
217
|
+
MCP Servers
|
|
218
|
+
</h2>
|
|
219
|
+
<button type="button" id="addServerToExistingCategoryBtn"
|
|
220
|
+
class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 flex items-center text-sm">
|
|
221
|
+
<i class='bx bx-plus mr-2'></i>
|
|
222
|
+
Add MCP Server
|
|
223
|
+
</button>
|
|
224
|
+
</div>
|
|
225
|
+
<div id="existingCategoryServersList" class="space-y-4">
|
|
226
|
+
<!-- Server configurations will be added here: existing ones read-only, new ones editable -->
|
|
227
|
+
</div>
|
|
132
228
|
</div>
|
|
229
|
+
|
|
230
|
+
<!-- Action Buttons -->
|
|
133
231
|
<div class="flex justify-end space-x-4 pt-6 border-t">
|
|
134
232
|
<button type="button" onclick="window.location.href='index.html'"
|
|
135
233
|
class="px-6 py-2.5 border border-gray-300 rounded-lg text-gray-600 hover:bg-gray-50">
|
|
136
234
|
Cancel
|
|
137
235
|
</button>
|
|
138
|
-
<button type="
|
|
236
|
+
<button type="button" id="validateButtonExistingCategory"
|
|
237
|
+
class="px-6 py-2.5 bg-green-500 text-white rounded-lg hover:bg-green-600 flex items-center">
|
|
238
|
+
<i class='bx bx-check-shield mr-2'></i>
|
|
239
|
+
Validate
|
|
240
|
+
</button>
|
|
241
|
+
<button type="submit" id="publishButtonExistingCategory"
|
|
139
242
|
class="px-6 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 flex items-center">
|
|
140
|
-
<i class='bx
|
|
141
|
-
|
|
243
|
+
<i class='bx bxs-cloud-upload mr-2'></i>
|
|
244
|
+
Publish
|
|
142
245
|
</button>
|
|
143
246
|
</div>
|
|
247
|
+
|
|
248
|
+
<!-- Validation Status Panel -->
|
|
249
|
+
<div id="validationStatusPanelExistingCategory" class="hidden p-6 bg-gray-50 rounded-lg border border-gray-200">
|
|
250
|
+
<h3 onclick="toggleSectionContent('validationStatusContentExistingCategoryTab', this.querySelector('.toggle-icon'))" class="cursor-pointer text-lg font-semibold text-gray-800 mb-3 flex items-center justify-between">
|
|
251
|
+
<span class="flex items-center">
|
|
252
|
+
<i class='bx bx-analyse mr-2 text-blue-600'></i>Validation Status
|
|
253
|
+
</span>
|
|
254
|
+
<i class='bx bx-chevron-down toggle-icon text-xl text-gray-500'></i>
|
|
255
|
+
</h3>
|
|
256
|
+
<div id="validationStatusContentExistingCategoryTab" class="text-sm text-gray-700 space-y-2">
|
|
257
|
+
<!-- Validation messages will be displayed here -->
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
144
260
|
</form>
|
|
145
261
|
</div>
|
|
262
|
+
|
|
263
|
+
<!-- JSON Editor Panel -->
|
|
264
|
+
<div id="panel-json-editor" class="hidden">
|
|
265
|
+
<h2 class="text-xl font-semibold text-gray-900 flex items-center mb-4">
|
|
266
|
+
<i class='bx bx-code-alt mr-2 text-blue-600'></i>
|
|
267
|
+
Edit Configuration as JSON
|
|
268
|
+
</h2>
|
|
269
|
+
<div class="relative">
|
|
270
|
+
<button type="button" onclick="copyJsonToClipboard()" title="Copy JSON to clipboard"
|
|
271
|
+
class="absolute top-2 right-2 z-10 px-3 py-1.5 text-xs bg-gray-200 hover:bg-gray-300 text-gray-700 rounded-md flex items-center">
|
|
272
|
+
<i class='bx bx-copy mr-1'></i> Copy
|
|
273
|
+
</button>
|
|
274
|
+
<textarea id="jsonEditorTextarea" rows="20"
|
|
275
|
+
class="w-full px-3 py-2 font-mono text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
276
|
+
placeholder="JSON configuration will appear here..."></textarea>
|
|
277
|
+
</div>
|
|
278
|
+
<div id="jsonEditorActionsContainer" class="flex justify-end space-x-4 pt-6 border-t mt-6">
|
|
279
|
+
<!-- "Apply JSON to Form" button removed -->
|
|
280
|
+
<button type="button" onclick="window.location.href='index.html'"
|
|
281
|
+
class="px-6 py-2.5 border border-gray-300 rounded-lg text-gray-600 hover:bg-gray-50">
|
|
282
|
+
Cancel
|
|
283
|
+
</button>
|
|
284
|
+
<button type="button" id="saveJsonButton"
|
|
285
|
+
class="px-6 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 flex items-center">
|
|
286
|
+
<i class='bx bxs-cloud-upload mr-2'></i>
|
|
287
|
+
Publish JSON
|
|
288
|
+
</button>
|
|
289
|
+
</div>
|
|
290
|
+
</div>
|
|
146
291
|
</div>
|
|
147
292
|
|
|
148
293
|
<script src="js/onboard/index.js" type="module"></script>
|
|
294
|
+
<!-- Highlight.js script can be removed if not using <pre><code> for JSON -->
|
|
149
295
|
</body>
|
|
150
296
|
</html>
|
|
@@ -152,4 +152,94 @@ body {
|
|
|
152
152
|
outline: none;
|
|
153
153
|
border-color: #2563eb;
|
|
154
154
|
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
|
|
155
|
-
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/* Onboarding form styles */
|
|
158
|
+
|
|
159
|
+
/* Form field styles */
|
|
160
|
+
input[type="text"],
|
|
161
|
+
input[type="url"],
|
|
162
|
+
select,
|
|
163
|
+
textarea {
|
|
164
|
+
transition: all 0.2s ease;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
input[type="text"]:focus,
|
|
168
|
+
input[type="url"]:focus,
|
|
169
|
+
select:focus,
|
|
170
|
+
textarea:focus {
|
|
171
|
+
outline: none;
|
|
172
|
+
border-color: #2563eb;
|
|
173
|
+
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* Radio button styles */
|
|
177
|
+
input[type="radio"] {
|
|
178
|
+
width: 1rem;
|
|
179
|
+
height: 1rem;
|
|
180
|
+
border: 2px solid #d1d5db;
|
|
181
|
+
border-radius: 50%;
|
|
182
|
+
transition: all 0.2s ease;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
input[type="radio"]:checked {
|
|
186
|
+
border-color: #2563eb;
|
|
187
|
+
background-color: #2563eb;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/* Remove button styles */
|
|
191
|
+
.remove-button {
|
|
192
|
+
color: #dc2626;
|
|
193
|
+
transition: all 0.2s ease;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.remove-button:hover {
|
|
197
|
+
color: #b91c1c;
|
|
198
|
+
background-color: #fee2e2;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/* Add button styles */
|
|
202
|
+
.add-button {
|
|
203
|
+
background-color: #f3f4f6;
|
|
204
|
+
transition: all 0.2s ease;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.add-button:hover {
|
|
208
|
+
background-color: #e5e7eb;
|
|
209
|
+
transform: translateY(-1px);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/* Form section headings */
|
|
213
|
+
.section-heading {
|
|
214
|
+
color: #1f2937;
|
|
215
|
+
font-size: 1.25rem;
|
|
216
|
+
font-weight: 600;
|
|
217
|
+
margin-bottom: 1rem;
|
|
218
|
+
display: flex;
|
|
219
|
+
align-items: center;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.section-heading i {
|
|
223
|
+
color: #2563eb;
|
|
224
|
+
margin-right: 0.5rem;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/* Required field indicator */
|
|
228
|
+
.required-field::after {
|
|
229
|
+
content: "*";
|
|
230
|
+
color: #dc2626;
|
|
231
|
+
margin-left: 0.25rem;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* Form grid layouts */
|
|
235
|
+
.form-grid {
|
|
236
|
+
display: grid;
|
|
237
|
+
gap: 1rem;
|
|
238
|
+
margin-bottom: 1.5rem;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
@media (min-width: 768px) {
|
|
242
|
+
.form-grid {
|
|
243
|
+
grid-template-columns: repeat(2, 1fr);
|
|
244
|
+
}
|
|
245
|
+
}
|
package/dist/web/server.d.ts
CHANGED
|
@@ -1,11 +1 @@
|
|
|
1
|
-
import { ServerInstallOptions } from '../core/types.js';
|
|
2
|
-
export interface UpdateRequirementsRequestBody {
|
|
3
|
-
requirements: {
|
|
4
|
-
name: string;
|
|
5
|
-
updateVersion: string;
|
|
6
|
-
}[];
|
|
7
|
-
}
|
|
8
|
-
export interface InstallServersRequestBody {
|
|
9
|
-
serverList: Record<string, ServerInstallOptions>;
|
|
10
|
-
}
|
|
11
1
|
export declare function startWebServer(port?: number): Promise<void>;
|
package/dist/web/server.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
+
import { OnboardingProcessStatus } from '../core/onboard/OnboardStatus.js';
|
|
4
5
|
import { SUPPORTED_CLIENT_NAMES } from '../core/constants.js';
|
|
5
6
|
import { serverService } from '../services/ServerService.js';
|
|
7
|
+
import { feedOnboardService } from '../core/onboard/FeedOnboardService.js';
|
|
6
8
|
import { openBrowser } from '../utils/osUtils.js';
|
|
7
9
|
import { Logger } from '../utils/logger.js';
|
|
8
10
|
import { configProvider } from '../core/ConfigurationProvider.js';
|
|
11
|
+
import { onboardStatusManager } from '../core/onboard/OnboardStatusManager.js';
|
|
9
12
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
13
|
const app = express();
|
|
11
14
|
// Middleware
|
|
@@ -52,31 +55,31 @@ app.get('/api/categories', async (req, res) => {
|
|
|
52
55
|
error: message
|
|
53
56
|
});
|
|
54
57
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
error: `Schema not found for server ${serverName} in category ${categoryName}`
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
const response = {
|
|
67
|
-
success: true,
|
|
68
|
-
data: schema
|
|
69
|
-
};
|
|
70
|
-
res.json(response);
|
|
71
|
-
}
|
|
72
|
-
catch (error) {
|
|
73
|
-
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
74
|
-
res.status(500).json({
|
|
58
|
+
});
|
|
59
|
+
// Get server schema
|
|
60
|
+
app.get('/api/categories/:categoryName/servers/:serverName/schema', async (req, res) => {
|
|
61
|
+
try {
|
|
62
|
+
const { categoryName, serverName } = req.params;
|
|
63
|
+
const schema = await serverService.getServerSchema(categoryName, serverName);
|
|
64
|
+
if (!schema) {
|
|
65
|
+
return res.status(404).json({
|
|
75
66
|
success: false,
|
|
76
|
-
error: `
|
|
67
|
+
error: `Schema not found for server ${serverName} in category ${categoryName}`
|
|
77
68
|
});
|
|
78
69
|
}
|
|
79
|
-
|
|
70
|
+
const response = {
|
|
71
|
+
success: true,
|
|
72
|
+
data: schema
|
|
73
|
+
};
|
|
74
|
+
res.json(response);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
78
|
+
res.status(500).json({
|
|
79
|
+
success: false,
|
|
80
|
+
error: `Failed to get schema for server ${req.params.serverName} in category ${req.params.categoryName}: ${message}`
|
|
81
|
+
});
|
|
82
|
+
}
|
|
80
83
|
});
|
|
81
84
|
// Get categories data (including feed configuration)
|
|
82
85
|
app.get('/api/categories/:categoryName', async (req, res) => {
|
|
@@ -103,6 +106,7 @@ app.get('/api/categories/:categoryName', async (req, res) => {
|
|
|
103
106
|
});
|
|
104
107
|
}
|
|
105
108
|
});
|
|
109
|
+
// Handle server category onboarding
|
|
106
110
|
// Install servers for a category
|
|
107
111
|
app.post('/api/categories/:categoryName/install', async (req, res) => {
|
|
108
112
|
try {
|
|
@@ -130,6 +134,111 @@ app.post('/api/categories/:categoryName/install', async (req, res) => {
|
|
|
130
134
|
});
|
|
131
135
|
}
|
|
132
136
|
});
|
|
137
|
+
// Handle server category onboarding
|
|
138
|
+
app.post('/api/categories/onboard', async (req, res) => {
|
|
139
|
+
try {
|
|
140
|
+
const { categoryData, forExistingCategory } = req.body; // Extract forExistingCategory from request body
|
|
141
|
+
// Basic validation for categoryData presence and essential fields for this endpoint
|
|
142
|
+
if (!categoryData || !categoryData.name || !categoryData.displayName) {
|
|
143
|
+
return res.status(400).json({
|
|
144
|
+
success: false,
|
|
145
|
+
error: 'Category data, including name and display name, is required.'
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
// categoryData is now expected to be a FeedConfiguration object directly from the client
|
|
149
|
+
const feedConfiguration = categoryData;
|
|
150
|
+
// Structural validation is now primarily handled by FeedOnboardService.validateStaticConfig
|
|
151
|
+
// The service will throw an error if the structure is invalid, which will be caught by the catch block below.
|
|
152
|
+
const operationResult = await feedOnboardService.onboardFeed(feedConfiguration, forExistingCategory);
|
|
153
|
+
// The response now directly reflects the OperationStatus returned by the service.
|
|
154
|
+
// The client will use data.onboardingId (which is the categoryName) to poll for status updates.
|
|
155
|
+
const response = {
|
|
156
|
+
success: operationResult.status !== OnboardingProcessStatus.FAILED, // Or a more nuanced success check
|
|
157
|
+
// Ensure data.onboardingId is the categoryName for polling
|
|
158
|
+
data: { ...operationResult, onboardingId: feedConfiguration.name }
|
|
159
|
+
};
|
|
160
|
+
res.status(operationResult.status === OnboardingProcessStatus.FAILED ? 500 : 200).json(response);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
164
|
+
res.status(500).json({
|
|
165
|
+
success: false,
|
|
166
|
+
error: `Failed to ${req.body.isUpdate ? 'update' : 'create'} server category: ${message}`
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
// Validate feed configuration
|
|
171
|
+
app.post('/api/categories/onboard/validate', async (req, res) => {
|
|
172
|
+
try {
|
|
173
|
+
const { categoryData, forExistingCategory } = req.body;
|
|
174
|
+
if (!categoryData || !categoryData.name) {
|
|
175
|
+
return res.status(400).json({
|
|
176
|
+
success: false,
|
|
177
|
+
error: 'Category name is required in categoryData for validation.'
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
// categoryData is now expected to be a FeedConfiguration object directly from the client
|
|
181
|
+
const feedConfigurationToValidate = categoryData;
|
|
182
|
+
// Structural validation is now primarily handled by FeedOnboardService.validateStaticConfig
|
|
183
|
+
// The service will throw an error if the structure is invalid, which will be caught by the catch block below.
|
|
184
|
+
// Call the service, which now returns OperationStatus & { feedConfiguration? }
|
|
185
|
+
// serverName parameter has been removed from validateFeed
|
|
186
|
+
const validationOperationResult = await feedOnboardService.validateFeed(feedConfigurationToValidate, forExistingCategory);
|
|
187
|
+
// The response includes the operation status and the feed configuration that was validated.
|
|
188
|
+
// The client will use data.onboardingId (which is the categoryName) to poll for status updates.
|
|
189
|
+
const response = {
|
|
190
|
+
success: validationOperationResult.status !== OnboardingProcessStatus.FAILED,
|
|
191
|
+
// Ensure data.onboardingId is the categoryName for polling
|
|
192
|
+
data: { ...validationOperationResult, onboardingId: feedConfigurationToValidate.name }
|
|
193
|
+
};
|
|
194
|
+
res.status(validationOperationResult.status === OnboardingProcessStatus.FAILED ? 500 : 200).json(response);
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
198
|
+
res.status(500).json({
|
|
199
|
+
success: false,
|
|
200
|
+
error: `Failed to validate server category: ${message}`
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
// Get category onboarding/validation operation status
|
|
205
|
+
app.get('/api/categories/:categoryName/onboard/status', async (req, res) => {
|
|
206
|
+
try {
|
|
207
|
+
const { categoryName } = req.params;
|
|
208
|
+
// categoryName is now the identifier for the operation status
|
|
209
|
+
const status = await onboardStatusManager.getStatus(categoryName);
|
|
210
|
+
if (!status) {
|
|
211
|
+
return res.status(404).json({
|
|
212
|
+
success: false,
|
|
213
|
+
error: `No active operation found for category ${categoryName}`
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
// Construct the response data based on the retrieved OnboardStatus
|
|
217
|
+
const responseData = {
|
|
218
|
+
onboardingId: status.onboardingId, // This will be the categoryName
|
|
219
|
+
status: status.status,
|
|
220
|
+
message: status.currentStep || status.errorMessage || 'Processing...',
|
|
221
|
+
lastQueried: new Date().toISOString(),
|
|
222
|
+
...(status.validationStatus && { validationStatus: status.validationStatus }),
|
|
223
|
+
...(status.prInfo && { prInfo: status.prInfo }),
|
|
224
|
+
...(status.result && { result: status.result }),
|
|
225
|
+
...(status.errorMessage && { errorMessage: status.errorMessage }),
|
|
226
|
+
...(status.operationType && { operationType: status.operationType }),
|
|
227
|
+
};
|
|
228
|
+
const response = {
|
|
229
|
+
success: true,
|
|
230
|
+
data: responseData
|
|
231
|
+
};
|
|
232
|
+
res.json(response);
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
236
|
+
res.status(500).json({
|
|
237
|
+
success: false,
|
|
238
|
+
error: `Failed to get operation status for category ${req.params.categoryName}: ${message}`
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
});
|
|
133
242
|
// Uninstall tools from a server
|
|
134
243
|
app.post('/api/categories/:categoryName/uninstall', async (req, res) => {
|
|
135
244
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "imcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"description": "Node.js SDK for Model Context Protocol (MCP)",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"test": "jest",
|
|
16
16
|
"lint": "eslint src --ext .ts",
|
|
17
17
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
18
|
-
"copy-public": "xcopy /E /I /Y src
|
|
18
|
+
"copy-public": "node -e \"const fs=require('fs'); const path=require('path'); const cp=require('child_process'); const cmd=process.platform==='win32' ? 'xcopy /E /I /Y src\\\\web\\\\public dist\\\\web\\\\public' : 'cp -r src/web/public dist/web/'; cp.execSync(cmd)\""
|
|
19
19
|
},
|
|
20
20
|
"keywords": [
|
|
21
21
|
"mcp",
|