imcp 0.0.11 → 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.
@@ -30,28 +30,26 @@ function showToast(message, type = 'success') {
30
30
  });
31
31
  }
32
32
 
33
- // Function to show a Bootstrap confirmation dialog
34
- function showConfirm(message) {
33
+ // Function to show a confirmation dialog using custom modal system
34
+ function showConfirm(title, message) {
35
35
  return new Promise((resolve) => {
36
36
  const modalId = `confirm-modal-${Date.now()}`;
37
37
  const modalHtml = `
38
- <div class="modal fade" id="${modalId}" tabindex="-1" aria-labelledby="${modalId}-label" aria-hidden="true">
39
- <div class="modal-dialog">
40
- <div class="modal-content">
41
- <div class="modal-header">
42
- <h5 class="modal-title" id="${modalId}-label">Confirm Action</h5>
43
- <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
44
- </div>
45
- <div class="modal-body">
46
- ${message}
47
- </div>
48
- <div class="modal-footer">
49
- <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
50
- <button type="button" class="btn btn-primary confirm-action">
51
- <span class="spinner-border spinner-border-sm d-none me-2" role="status" aria-hidden="true"></span>
52
- Confirm
53
- </button>
54
- </div>
38
+ <div id="${modalId}" class="modal">
39
+ <div class="modal-content" style="max-width: 400px; margin: 15% auto;">
40
+ <div class="modal-header">
41
+ <h3 class="text-lg font-semibold text-gray-700">${title}</h3>
42
+ </div>
43
+ <div style="margin: 1rem 0;">
44
+ ${message}
45
+ </div>
46
+ <div style="display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 1rem;">
47
+ <button type="button" class="cancel-button px-4 py-2 text-gray-600 hover:text-gray-800 font-medium rounded-lg hover:bg-gray-100 transition-colors">
48
+ Cancel
49
+ </button>
50
+ <button type="button" class="confirm-button submit-button">
51
+ Confirm
52
+ </button>
55
53
  </div>
56
54
  </div>
57
55
  </div>
@@ -60,29 +58,30 @@ function showConfirm(message) {
60
58
  document.body.insertAdjacentHTML('beforeend', modalHtml);
61
59
 
62
60
  const modalElement = document.getElementById(modalId);
63
- const modal = new bootstrap.Modal(modalElement);
61
+ modalElement.style.display = 'block';
64
62
 
65
63
  // Handle confirm button click
66
- modalElement.querySelector('.confirm-action').addEventListener('click', (event) => {
67
- const button = event.currentTarget;
68
- const spinner = button.querySelector('.spinner-border');
69
- button.disabled = true;
70
- spinner.classList.remove('d-none');
71
-
72
- // Add small delay to show the loading state
73
- setTimeout(() => {
74
- modal.hide();
75
- resolve(true);
76
- }, 300);
64
+ modalElement.querySelector('.confirm-button').addEventListener('click', () => {
65
+ modalElement.style.display = 'none';
66
+ modalElement.remove();
67
+ resolve(true);
77
68
  });
78
69
 
79
- // Handle modal hidden event
80
- modalElement.addEventListener('hidden.bs.modal', () => {
70
+ // Handle cancel button click
71
+ modalElement.querySelector('.cancel-button').addEventListener('click', () => {
72
+ modalElement.style.display = 'none';
81
73
  modalElement.remove();
82
74
  resolve(false);
83
75
  });
84
-
85
- modal.show();
76
+
77
+ // Handle click outside modal
78
+ modalElement.addEventListener('click', (event) => {
79
+ if (event.target === modalElement) {
80
+ modalElement.style.display = 'none';
81
+ modalElement.remove();
82
+ resolve(false);
83
+ }
84
+ });
86
85
  });
87
86
  }
88
87
 
package/src/web/server.ts CHANGED
@@ -32,7 +32,11 @@ export interface InstallServersRequestBody {
32
32
  }
33
33
 
34
34
  interface UninstallServersRequestBody {
35
- serverList: string[];
35
+ serverList: Record<string, { removeData?: boolean }>;
36
+ options: {
37
+ targets: string[];
38
+ removeData?: boolean;
39
+ };
36
40
  }
37
41
 
38
42
  interface ApiResponse<T> {
@@ -155,15 +159,29 @@ app.post('/api/categories/:categoryName/uninstall', async (req: Request<{ catego
155
159
  const { categoryName } = req.params;
156
160
  const { serverList } = req.body;
157
161
 
158
- if (!Array.isArray(serverList) || serverList.length === 0) {
162
+ if (!serverList || Object.keys(serverList).length === 0) {
159
163
  return res.status(400).json({
160
164
  success: false,
161
165
  error: 'Invalid tool list provided'
162
166
  });
163
167
  }
164
168
 
169
+ const { options } = req.body;
170
+ if (!options?.targets || options.targets.length === 0) {
171
+ return res.status(400).json({
172
+ success: false,
173
+ error: 'No target clients specified'
174
+ });
175
+ }
176
+
165
177
  const results = await Promise.all(
166
- serverList.map(serverName => serverService.uninstallMcpServer(categoryName, serverName))
178
+ Object.entries(serverList).map(([serverName, serverOptions]) =>
179
+ serverService.uninstallMcpServer(categoryName, serverName, {
180
+ ...serverOptions,
181
+ targets: options.targets,
182
+ removeData: options.removeData ?? serverOptions.removeData
183
+ })
184
+ )
167
185
  );
168
186
 
169
187
  const { success, messages } = serverService.formatOperationResults(results);